Java线程创建

80 阅读2分钟

如何创建线程?

  1. 继承 Thread 类

    public class MyThread extends Thread {
        public void run() {
            // 线程执行的任务
        }
    }
    

    创建线程并启动:

    MyThread myThread = new MyThread();
    myThread.start();
    
  2. 实现 Runnable 接口

    public class MyRunnable implements Runnable {
        public void run() {
            // 线程执行的任务
        }
    }
    

    创建线程并启动:

    Thread thread = new Thread(new MyRunnable());
    thread.start();
    

    以上代码也可以简化,直接使用匿名内部类或表达式:

    // 匿名内部类
    Thread thread1 = new Thread(new Runnable() {
        @Override
        public void run() {
            // 线程执行的任务
        }
    });
    thread1.start();
    
    // 表达式
    Thread thread2 = new Thread(() ->{
        // 线程执行的任务
    });
    thread2.start();
    
  3. 实现 Callable 接口

    public class MyCallable implements Callable<Integer> {
        public Integer call() {
            // 线程执行的任务,并返回一个结果
        }
    }
    

    创建线程对象并启动:

    FutureTask<Integer> futureTask = new FutureTask<>(new MyCallable());
    Thread thread = new Thread(futureTask);
    thread.start();
    
  4. 使用线程池

    ExecutorService executorService = Executors.newFixedThreadPool(1); 
    executorService.execute(new MyRunnable()); 
    executorService.shutdown();
    

扩展

通过代码可以发现,方法1-3虽然有所不同,但最终都需要通过创建Thread类,并调用start()方法来启动线程,它们有什么关系呢?

  1. Thread类的构造函数

屏幕截图 2024-01-16 215852.png

代码中用到的就是Thread()Thread(Runnable)两个构造方法。

但是不对呀,FutureTask明明也可以作为形参构造Thread对象?聪明的你一定已经想到了,没错,FutureTask实现了Runnable接口

image.png

可为什么表达式也可以作为Thread构造函数的形参?

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

查看源码可发现,Runnable接口上有个@FunctionalInterface注解,这个注解在jdk8被用于标记一个接口,如果这个接口只包含一个抽象方法,那么这个接口就是一个函数式接口,允许使用Lambda 表达式和函数式编程特性。

  1. RunnableCallable的使用区别:

两者都是实现了接口,但Callable允许线程返回一个结果,可以通过FutureTask.get()获取到线程的执行结果,如果调用的时候线程还没有执行完,那么会等线程执行完后再拿到结果。

但这个过程是怎样的呢?

  • 初始化FutureTask,设置state为0
public FutureTask(Callable<V> callable) {
    if (callable == null)
        throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;       // 值为0
}
  • 执行run()方法,修改state的值

屏幕截图 2024-01-16 225117.png

  • 获取结果
public V get() throws InterruptedException, ExecutionException {
    int s = state;
    // 如果线程未执行,s=0
    if (s <= COMPLETING)
        // 自旋等待线程执行完
        s = awaitDone(false, 0L);
    // 获取结果
    return report(s);
}