java从基础知识(十)java多线程(上)

  线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪阻塞运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。

  这一节介绍线程的启动方式及Thread类。

一、线程的启动方式

1、通过Thread类启动

public class ThreadTest extends Thread {

    private String name;

    public ThreadTest(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        for(int i = 0; i < 100; i++)
        System.out.println(name + " thread : " + i);
    }

    public static void main(String[] args) {
        ThreadTest tt1 = new ThreadTest("tt1");
        tt1.start();//使该线程开始执行;Java 虚拟机调用该线程的 run 方法
        ThreadTest tt2 = new ThreadTest("tt2");
        tt2.start();
    }
}

  注意:线程是通过start的方法启动的,run方法是用来实现逻辑的。

2、通过Runnable接口启动

public class RunnableTest implements Runnable {

    private String name;

    public RunnableTest(String name) {
        this.name = name;
    }

    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(name + " runnabel : " + i);
        }
    }

    public static void main(String[] args) {
        RunnableTest rt1 = new RunnableTest("rt1");
        Thread t1 = new Thread(rt1);
        t1.start();
        RunnableTest rt2 = new RunnableTest("rt2");
        Thread t2 = new Thread(rt2);
        t2.start();
    }
}

3、使用ExecutorService、Callable、Future实现有返回结果的多线程

public class ExcuteTest {

    public static void main(String[] args) {
        System.out.println("----程序开始运行----");

        int taskSize = 5;
        // 创建一个线程池
        ExecutorService pool = Executors.newFixedThreadPool(taskSize);
        // 创建多个有返回值的任务
        List<Future> list = new ArrayList<Future>();
        for (int i = 1; i < taskSize + 1; i++) {
            Callable c = new MyCallable(i + " ");
            // 执行任务并获取Future对象
            Future f = pool.submit(c);
            list.add(f);
        }
        // 关闭线程池
        pool.shutdown();

        // 获取所有并发任务的运行结果
        try {
            for (Future f : list) {
                // 从Future对象上获取任务的返回值,并输出到控制台
                System.out.println("executor" + f.get().toString());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }
}

class MyCallable implements Callable<Object> {
    private String name;

    MyCallable(String name) {
        this.name = name;
    }

    public Object call() {
        for (int i = 0; i < 100; i++) {
            System.out.println(name + " : " + i);
        }
        return name + " end";
    }

}

二、Thread介绍

public class ThreadTest extends Thread {

    private String name;

    public ThreadTest(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println("返回当前线程的线程组中活动线程的数目 " + name + " : " + Thread.activeCount());
        System.out.println("返回对当前正在执行的线程对象的引用 " + name + " : " + Thread.currentThread());
        try {
            for (int i = 0; i < 100; i++) {
                Thread.currentThread().sleep(1);
                System.out.println(name + " thread : " + i);
                //Thread.currentThread().interrupt();//中断线程
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        ThreadTest tt1 = new ThreadTest("tt1");
        tt1.setName("t1");//改变线程名称,使之与参数 name 相同
        tt1.start();//使该线程开始执行;Java 虚拟机调用该线程的 run 方法

        System.out.println("返回该线程的标识符 tt1 : " + tt1.getId());
        System.out.println("返回该线程的名称 tt1 : " + tt1.getName());
        System.out.println("返回线程的优先级 tt1 : " + tt1.getPriority());
        System.out.println("返回该线程的状态 tt1 : " + tt1.getState());

        System.out.println("测试线程是否处于活动状态 tt1 : " + tt1.isAlive());
        System.out.println("测试当前线程是否已经中断 tt1 : " + tt1.isInterrupted());
        System.out.println("测试该线程是否为守护线程 tt1 : " + tt1.isDaemon());

        ThreadTest tt2 = new ThreadTest("tt2");
        tt2.setName("t2");
        System.out.println("返回线程的优先级 tt2 : " + tt2.getPriority());
        tt1.yield();//暂停当前正在执行的线程对象,并执行其他线程
        try {
            //tt1.join();//等待该线程终止
            tt1.join(10);//等待该线程终止的时间最长为 millis 毫秒
            //tt1.join(10, 10);//等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        tt2.start();
    }
}

三、Thread与Runnable的区别

1、Runnable方式可以避免Tread方式由于java单继承特性带来的缺陷。Runnable的代码可以被多个线程(Thread实例)共享,适合于多个线程处理同一资源的情况。

JAVA多线程实现的三种方式

Java总结篇系列:Java多线程(一)

时间: 2024-12-15 07:09:21

java从基础知识(十)java多线程(上)的相关文章

Java 接口基础知识

一.Java接口基础知识 1, Java语言不支持一个类有多个直接的父类(多继承),但可以实现(implements)多个接口,间接的实现了多继承. 2, 与Java接口相关的设计模式: 1, 定制服务模式 设计精粒度的接口,每个Java接口代表相关的一组服务,通过继承来创建复合接口 2, 适配器模式 当每个系统之间接口不匹配时,用适配器来转换接口 3, 默认适配器模式 为接口提供简单的默认实现 4, 代理模式 为Java接口的实现类创建代理类,使用者通过代理来获得实现类的服务 5, 标识类型模

什么才是java的基础知识?

近日里,很多人邀请我回答各种j2ee开发的初级问题,我无一都强调java初学者要先扎实自己的基础知识,那什么才是java的基础知识?又怎么样才算掌握了java的基础知识呢?这个问题还真值得仔细思考. 我做j2ee开发已经超过十载,作为过来人,心路历程估计和大家差不多.编码的前几年,很长一段时间觉得java简单,开发实现各种功能都很轻松,代码写起来根本不费劲(主要是因为写的代码都是一些功能业务逻辑).但同时自己心里明白,自己其实没有什么水平,自己这3,4年以来学懂的东西就那么多,其他人几个月就可以

Java Web基础知识之Filter:过滤一切你不想看到的事情

不要相信客户端, 所以做后端的人都应该铭记的事情.因为前端传过来的数据并不总是合法和有效的,所以后端是对访问资源的最后一道保护伞.之前我们在Spring中说到过AOP编程,AOP基础知识,它就可以在执行我们的方法之前进行一些预处理和验证来保护后端的资源.不难想到她的实现方式和本篇要说的过滤器的实现原理应该是相同的,都是通过Java的动态代理实现的(自己的理解). 在Java Web的开发中,过滤器用于拦截请求,并对ServletRequest对象进行处理,我们可以想到的,它可以用来验证权限.加密

Java Script基础(十二) 正则表达式

Java Script基础(十二) 正则表达式 一.正则表达式中常用的符号 虽然可以使用string函数来完成验证,但是这种验证方式不够严谨,而且编写比较麻烦.而正则表达式是一种描述字符模式的对象,由一些特殊的符号组成,其组成的字母模式用来匹配各种表达式.下表中列举出常用的符号和用法. 正则表达式中常用的符号和用法 符号 描述  /....../  代表一个模式的开始和结束.  ^  匹配字符串的开始   $  匹配字符串的结束  \s  任何空白字符   \S  任何非空白字符   \d  匹

java基础知识《JAVA 核心技术》学习笔记(一)

一:数据类型 (1)java整形: 类型                         存储要求 int                              4字节 short                          2字节 long                           8字节 byte                           1字节 (2)浮点类型 类型                         储存要求 float            

Java Script基础(十) 访问样式表

Java Script基础(十) 访问样式表 动态控制样式表 在JavaScript中,有两种方式可以动态的改变样式属性,一种是使用style属性,另一种是使用样式的className属性.另外控制元素隐藏和显示使用display属性. 1.使用sytle属性 语法: 元素.style.样式属性="值"; 在JavaScript中使用CSS样式与在html中使用CSS少有不同,由于JavaScript中的-表示减号,因此如果样式属性名称中带有"-"则要省去,后面首字

黑马程序员——Java集合基础知识之Map

Map概念 要同时存储两个元素Key和Value,他们之间有映射关系,每个键不能重复,每个键只能映射到一个值. 当数据之间存在映射关系的时候,考虑使用Map集合. Map常用方法 如果添加的键原来有值,后添加的值会覆盖前面的值,并返回之前的值.put会返回来先添加的值,后添加的值会覆盖原有的值. Map tm =new TreeMap(); tm.put (key, value);//MAP没有add tm.remove (key) ;//去除一个key和对应的value,若不存在key返回nu

黑马程序员——Java集合基础知识之Collection

集合基础知识--Collection Java中集合框架由常用的Collection接口和Map接口组成,而Collection接口又有两个子接口,是List接口和Set接口,常用的集合框架由这三个类组成. List接口的功能方法 List的使用最为简单,创建集合,通过add方法添加元素,get方法获取元素,通过迭代器获取元素.List接口存放的数据无序的,添加速度快,但是查询速度慢,因为查询的时候必须遍历,每次都重头开始,效率较低.常用实现类有ArrayList,LinkedList. Lis

Java web基础总结十之—— jsp EL表达式

Java web基础总结十之-- jsp EL表达式 一.EL表达式简介 EL 是Expression Language的缩写.在jsp中有很大的作用,EL主要有以下一些作用:获取数据,替换JSP页面中的脚本表达式,以从各种类型的web域中检索java对象.获取数据.还可以执行运算,利用EL表达式可以在JSP页面中执行一些基本的关系运算.逻辑运算和算术运算,以在JSP页面中完成一些简单的逻辑运算,例如 ${user==null}.还可以获取web开发常用的jsp的隐式对象,利用这些隐式对象,we

ASP.NET Core 2.2 基础知识(十六) SignalR 概述

原文:ASP.NET Core 2.2 基础知识(十六) SignalR 概述 我一直觉得学习的最好方法就是先让程序能够正常运行,才去学习他的原理,剖析他的细节. 就好像这个图: 所以,我们先跟着官方文档,创建一个 SignalR 应用: https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/signalr?view=aspnetcore-2.2&tabs=visual-studio 这个例子一共涉及到下面几个步骤: 自定义中心 ChatH