使用多线程时,不同方式最终都通过调用 Thread 类的 start 方法启动线程

1. 继承Thread类

  1. 继承Thread类
  2. 重写run()方法
    • 需要执行的代码写在方法体中
  3. 调用start()方法
public class ThreadCreate1 extends Thread{  
  
    @Override  
    public void run() {  
        System.out.println(Thread.currentThread().getName() + ": <子线程>-启动");  
  
        try {  
            Thread.sleep(3000);  
        } catch (InterruptedException e) {  
            throw new RuntimeException(e);  
        }  
  
        System.out.println(Thread.currentThread().getName() + ": <子线程>-结束");  
    }  
  
    public static void main(String[] args) {  
        System.out.println(Thread.currentThread().getName() + ": <主线程>-启动");  
        new ThreadCreate1().start();  
        new ThreadCreate1().start();  
        new ThreadCreate1().start();  
        System.out.println(Thread.currentThread().getName() + ": <主线程>-结束");  
    }  
}

2. 实现Runnable接口

  1. 实现Runnable接口
  2. 重写run()方法
    • 需要执行的代码写在方法体中
  3. 实例化Thread类,并传入Runnable接口实现类的实例,并调用start()方法
    • new Thread(new ThreadCreate2()).start();
public class ThreadCreate2 implements Runnable{  
    @Override  
    public void run() {  
        System.out.println(Thread.currentThread().getName() + ": <子线程>-启动");  
  
        try {  
            Thread.sleep(3000);  
        } catch (InterruptedException e) {  
            throw new RuntimeException(e);  
        }  
  
        System.out.println(Thread.currentThread().getName() + ": <子线程>-结束");  
    }  
  
    public static void main(String[] args) {  
        System.out.println(Thread.currentThread().getName() + ": <主线程>-启动");  
        new Thread(new ThreadCreate2()).start();  
        new Thread(new ThreadCreate2()).start();  
        new Thread(new ThreadCreate2()).start();  
        System.out.println(Thread.currentThread().getName() + ": <主线程>-结束");
	}

3. 匿名内部类实现Runnable接口

这种方式属于方法2的变体,在构造Thread类时传入一个Runnable实例,并实现run()方法即可

private static void main(String[] args) {
	System.out.println(Thread.currentThread().getName() + ": <主线程>-启动");  
    new Thread(new Runnable() {  
        @Override  
        public void run() {  
            System.out.println(Thread.currentThread().getName() + ": <子线程>-启动");  

            try {  
                Thread.sleep(3000);  
            } catch (InterruptedException e) {  
                throw new RuntimeException(e);  
            }  

            System.out.println(Thread.currentThread().getName() + ": <子线程>-结束");  
        }  
    }).start();  
    System.out.println(Thread.currentThread().getName() + ": <主线程>-结束");
}

4. lambda表达式

这种方式属于方法3的变体

  • new Thread(() -> { 方法内容…}).start;
private static void main(String[] args) {
	System.out.println(Thread.currentThread().getName() + ": <主线程>-启动");  
	new Thread(() -> {  
	    System.out.println(Thread.currentThread().getName() + ": <子线程>-启动");  
	  
	    try {  
	        Thread.sleep(3000);  
	    } catch (InterruptedException e) {  
	        throw new RuntimeException(e);  
	    }  
	  
	    System.out.println(Thread.currentThread().getName() + ": <子线程>-结束");  
	}).start();  
	System.out.println(Thread.currentThread().getName() + ": <主线程>-结束");
}

5. 实现Callable接口

不同:可以获取到返回值

  1. 实现Callable接口,泛型用于指定返回值的类型
  2. 实现call()方法
    • 需要执行的代码写在方法体中
  3. 实例化FutureTask,并传入Callable接口实现类的实例,泛型用于指定返回值类型
  4. 实例化Thread类,并传入FutureTasks实例,并调用start()方法
  5. 调用FutureTask实例的get()方法,可以获得子线程返回值

分析:

Integer result = futureTask.get();

// 获取子线程返回值时,主线程会等待子线程任务结束  
// 相当于:  

LockSupport.park();  
Integer result = futureTask.get();  
LockSupport.unPark();

6. 线程池

  1. 创建线程池
    • ExecutorService executorService = Executors.newCachedThreadPool();
  2. 调用线程池的execute()方法,执行线程任务
    • executorService.execute(() -> {})
    • 传入的内容可以是Runnable接口的实现,也可以是Callable接口的实现
  • 线程池 - Runnable接口
public class ThreadCreate4 {  
    static ExecutorService executorService = Executors.newCachedThreadPool();  
  
    public static void main(String[] args) {  
        System.out.println(Thread.currentThread().getName() + ": <主线程>-启动");  
        executorService.execute(() -> {  
            System.out.println(Thread.currentThread().getName() + ": <子线程>-启动");  
  
            try {  
                Thread.sleep(3000);  
            } catch (InterruptedException e) {  
                throw new RuntimeException(e);  
            }  
  
            System.out.println(Thread.currentThread().getName() + ": <子线程>-结束");  
        });  
        System.out.println(Thread.currentThread().getName() + ": <主线程>-结束");  
    }  
}
  • 线程池 - Callable接口
public class ThreadCreate5 {  
    public static void main(String[] args) {  
        ExecutorService executorService = Executors.newCachedThreadPool();  
        FutureTask<Integer> futureTask = new FutureTask<>(() -> {  
            System.out.println(Thread.currentThread().getName() + ": <子线程>-启动");  
            try {  
                Thread.sleep(3000);  
            } catch (InterruptedException e) {  
                throw new RuntimeException(e);  
            }  
  
            System.out.println(Thread.currentThread().getName() + ": <子线程>-结束,返回值:1");  
            return 1;  
        });  
        executorService.execute(futureTask);  
        try {  
            Integer result = futureTask.get();  
            System.out.println(Thread.currentThread().getName() + ": <主线程>-获取结果为" + result);  
        } catch (InterruptedException | ExecutionException e) {  
            throw new RuntimeException(e);  
        }  
    }  
}