1-创建线程

1 直接使用Thread

创建Thread的匿名子类,重写 run 方法:

public static void main(String[] args) throws ExecutionException,InterruptedException {
    // 创建线程对象,并给个别名
    Thread t1 = new Thread("t1") {
        @Override
        public void run() {
            int a = 0;
            a += 10;
        }
    };
    // 启动线程
    t1.start();
}

Thread 有另一个更简便的构造器,只需传入一个 Runnable 对象:

image-20210122161206422

又因为 Runnable 是一个函数式接口:

image-20210122160644682

所以就可以用 lambda 表达式简化写法:

public static void main(String[] args) throws ExecutionException,InterruptedException {
    // lambda表达式重写 run 方法,方法体即是线程的任务 
    Thread t2 = new Thread(() -> {
        int a = 10;
        a += 10;
    }, "t2");
    t2.start();
}

2 使用 Runnable 配合 Thread

把 Runnable 对象抽出来:

public static void main(String[] args) throws ExecutionException,InterruptedException {

    // 创建任务对象
    Runnable task = () -> log.debug("hello");
    // 参数1 是任务对象; 参数2 是线程名字,推荐
    Thread t2 = new Thread(task, "t2");
    t2.start();
}

该方式将任务和线程分开了,这样写有两个优点:

  • 使用 Runnable 让任务类脱离了 Thread 继承体系,更灵活
  • 使用 Runnable 也更容易与线程池等高级 API 配合

3 FutureTask 配合 Thread

FutureTask 也是一个任务类,用法和 Runnable 相似,但是 FutureTask 具有返回值

它的构造器会传入的是一个 Callable 对象:

image-20210122161952714

可以在其他线程中使用 FutureTask对象.get 来等待返回值。

public static void main(String[] args) throws ExecutionException,InterruptedException {
    // 创建FutureTask对象,传入一个 Callable 
    FutureTask<Integer> task = new FutureTask<>(() -> {
        log.debug("hello");
        return 100;
    });
    
    // 创建线程并启动
    new Thread(task, "t3").start();
    
    // 主线程调用 get 方法会阻塞等待 task 执行完毕的返会结果
    Integer result = task.get();
    log.debug("结果是:{}", result);
}
posted @ 2021-01-22 16:28  卡文迪雨  阅读(90)  评论(0编辑  收藏  举报