1.2 多线程 - 线程的创建

2018-06-26  本文已影响8人  Hey_Shaw

每个线程的作用是完成一定的任务,实际就是执行一段程序流(一段顺序执行的代码)。Java使用线程执行体来代表这段程序流。

继承 Thread 类创建线程类

创建并启动多线程的步骤如下:

代码示例:

// 通过继承Thread类来创建线程类
public class FirstThread extends Thread { 
    private int i ;
    // 重写run方法,run方法的方法体就是线程执行体
    public void run() {
        for ( ; i < 100 ; i++ ){
            // 当线程类继承Thread类时,直接使用this即可获取当前线程
            // Thread对象的getName()返回当前该线程的名字
            // 因此可以直接调用getName()方法返回当前线程的名
            System.out.println(getName() +  " " + i);
        }
    }
    public static void main(String[] args){
        for (int i = 0; i < 100;  i++){
            // 调用Thread的currentThread方法获取当前线程
            System.out.println(Thread.currentThread().getName()
                +  " " + i);
            if (i == 20){
                // 创建、并启动第一条线程
                new FirstThread().start();
                // 创建、并启动第二条线程
                new FirstThread().start();
            }
        }
    }
}

Java 程序开始运行后,程序至少会创建一个主线程,主线程的线程执行体不是由 run() 方法确定的,而是由 main() 方法确定的 —— main() 方法的方法体代表主线程的线程执行体。

实现 Runnable 接口创建线程类

创建并启动多线程的步骤如下:

代码示例:

// 通过实现Runnable接口来创建线程类
public class SecondThread implements Runnable {
    private int i ;
    // run方法同样是线程执行体
    public void run()   {
        for ( ; i < 100 ; i++ ) {
            // 当线程类实现Runnable接口时,
            // 如果想获取当前线程,只能用Thread.currentThread()方法。
            System.out.println(Thread.currentThread().getName()
                + "  " + i);
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100;  i++) {
            System.out.println(Thread.currentThread().getName()
                + "  " + i);
            if (i == 20) {
                SecondThread st = new SecondThread();     // ①
                // 通过new Thread(target , name)方法创建新线程
                new Thread(st , "新线程1").start();
                new Thread(st , "新线程2").start();
            }
        }
    }
}

Runnable 对象仅仅作为 Thread 对象的 target ,Runnable 实现类里包含的 run() 方法仅作为线程体。而实际的线程对象依然是 Thread 实例,只是该 Thread 线程负责执行其target 的 run() 方法。总结来说:FirstThread 直接创建的 Thread 子类即可代表线程对象;SecondThread 创建的 Runnable 对象只能作为线程对象的 target。
采用 Runnable 接口的方式创建的多个线程可以共享线程类的实例变量。

使用 Callable 和 Future 创建线程

Callable 接口提供了一个 call() 方法可以作为线程执行体:

Callable 接口是Java5新增的接口,并不是 Runnable 接口的子接口,所以不能直接作为 Thread 的 target。call() 方法并不是直接调用,它是作为线程执行体被调用的。

Java5 提供了 Futurn 接口来代表 Callable 接口里 call() 的返回值,并为 Future 接口提供一个 FutureTask 实现类,该实现类实现了 Futurn 接口,并实现了 Runable 接口 —— 可以作为 Thread 类的 target 。

Futurn 接口里定义了如下方法来控制它关联的 Callable 任务

Callable 接口有泛型限制,Callable 接口里的泛型形参类型与 call() 方法返回值类型相同。

创建并启动有返回值的多线程的步骤如下:

代码示例:

public class ThirdThread{
    public static void main(String[] args){
        // 创建Callable对象
        ThirdThread rt = new ThirdThread();
        // 先使用Lambda表达式创建Callable<Integer>对象
        // 使用FutureTask来包装Callable对象
        FutureTask<Integer> task = new FutureTask<Integer>((Callable<Integer>)() -> {
            int i = 0;
            for ( ; i < 100 ; i++ ){
                System.out.println(Thread.currentThread().getName()
                    + " 的循环变量i的值:" + i);
            }
            // call()方法可以有返回值
            return i;
        });
        for (int i = 0 ; i < 100 ; i++){
            System.out.println(Thread.currentThread().getName()
                + " 的循环变量i的值:" + i);
            if (i == 20){
                // 实质还是以Callable对象来创建、并启动线程
                new Thread(task , "有返回值的线程").start();
            }
        }
        try{
            // 获取线程返回值
            System.out.println("子线程的返回值:" + task.get());
        }
        catch (Exception ex){
            ex.printStackTrace();
        }
    }
}

创建线程的三种方式对比

上一篇 下一篇

猜你喜欢

热点阅读