创建线程的三种方式

废话不说,直接上代码

继承Thread类

// 继承Thread
class MyThread extends Thread {
    // 重写run方法执行任务
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            // 可以通过this拿到当前线程
            System.out.println(this.getName()+"执行了"+i);
        }
    }
}

public class Demo_02_02_1_ThreadCreateWays {
    public static void main(String[] args) {
        // 先new出来,然后启动
        MyThread myThread = new MyThread();
        myThread.start();
        for (int i = 0; i < 10; i++) {
            // 通过Thread的静态方法拿到当前线程
            System.out.println(Thread.currentThread().getName()+"执行了"+i);
        }
    }
}

实现Runnable

// 实现Runnable接口
class MyThreadByRunnable implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            // 不能用this了
            System.out.println(Thread.currentThread().getName() + "执行了" + i);
        }
    }
}

public class Demo_02_02_1_ThreadCreateWays {
    public static void main(String[] args) {
        // 实现Runnable接口的方式启动线程
        Thread thread = new Thread(new MyThreadByRunnable());
        thread.start();
        for (int i = 0; i < 10; i++) {
            // 通过Thread的静态方法拿到当前线程
            System.out.println(Thread.currentThread().getName() + "执行了" + i);
        }
    }
}

用lamba也可以

new Thread(() -> {
    System.out.println("Runnable是函数式接口, java8也可以使用lamba");
}).start();

使用Callable和Future

// 使用Callable
class MyThreadByCallable implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"执行了"+i);
            sum+=i;
        }
        return sum;
    }
}
public class Demo_02_02_1_ThreadCreateWays {
    public static void main(String[] args) {
        // 用FutureTask包一层
        FutureTask<Integer> futureTask = new FutureTask<>(new MyThreadByCallable());
        new Thread(futureTask).start();
        try {
            // 调用futureTask的get能拿到返回的值
            System.out.println(futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

这是最复杂的一种方式,他可以有返回值,归纳一下步骤:

  1. 搞一个类实现Callable接口,重写call方法,在call执行任务
  2. FutureTask包装实现Callable接口类的实例
  3. FutureTask的实例作为Thread构造参数
  4. 调用FutureTask实例的get拿到返回值,调这一句会阻塞父线程

Callable也是函数式接口,所以也能用lamba

为啥Thread构造里边能方Runnable,也能放FutureTask? 其实FutureTask继承RunnableFuture,而RunnableFuture继承Runnable和Future,注意接口是可以多继承的

三种方式比较

方式 使用简易程度 是否可以共享任务代码 是否可以有返回值 是否可以声明抛出异常 是否可以再继承别的类
继承Thread 简单 不能 不能 不能 不能
Runnable 中等 可以 不能 不能 可以
Callable 复杂 可以 可以 可以 可以

继承Thread是最容易的,但是也是最不灵活的

使用Callable时最复杂的,但是也是最灵活的

这里说的共享任务代码举个例子:

还是上面那个MyThreadByRunnable

MyThreadByRunnable myThreadByRunnable = new MyThreadByRunnable();
Thread thread = new Thread(myThreadByRunnable);
thread.start();
// 再来一个,复用了任务代码,继承Thread就不行
Thread thread2 = new Thread(myThreadByRunnable);
thread2.start();

results matching ""

    No results matching ""