一、介绍
- 与继承Thread类和实现Runnable接口两种创建线程方式的区别
① Callable接口可以有返回值
② Callable接口可以抛出异常
③ 执行方法不同,call()方法和run()方法
二、代码演示
-
继承Thread类和实现Runnable接口的方式创建线程
package callable; import java.util.concurrent.TimeUnit; /** * @author swaggyhang * @create 2023-07-04 19:41 */ public class Test01 { public static void main(String[] args) { // 1. 继承Thread类 for (int i = 1; i <= 10; i++) { MyThread myThread = new MyThread(); myThread.setName(String.valueOf(i)); myThread.start(); } try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } // 2. 实现Runnable接口 for (int i = 1; i <= 10; i++) { Thread thread = new Thread(new MyThread1()); thread.setName(String.valueOf(i)); thread.start(); } } } class MyThread extends Thread { @Override public void run() { System.out.println(Thread.currentThread().getName()); } } class MyThread1 implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName()); } }
-
Callable接口的方式创建线程
package callable; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; /** * @author swaggyhang * @create 2023-07-04 20:12 */ public class Test02 { public static void main(String[] args) throws ExecutionException, InterruptedException { for (int i = 1; i <= 10; i++) { // FutureTask是Runnable接口的一个实现类 // FutureTask构造器接收Callable参数 FutureTask<String> futureTask = new FutureTask<>(new MyThread3()); new Thread(futureTask, String.valueOf(i)).start(); // futureTask.get()方法可能会产生阻塞,一般是放在程序最后 // 或者使用异步通信来处理! System.out.println(futureTask.get()); } } } class MyThread3 implements Callable<String> { @Override public String call() throws Exception { return "call():" + Thread.currentThread().getName(); } }
-
Callable接口的返回结果是有缓存的,两个线程同时调用,会获取同一个返回值
-
Callable接口的返回结果可能需要等待,会出现阻塞