1 package day2_6;
2
3 import java.util.concurrent.Callable;
4 import java.util.concurrent.ExecutionException;
5 import java.util.concurrent.FutureTask;
6
7 /**
8 * 创建线程的方式三:实现Callable接口。 ---JDK5.0新增
9 *
10 * 如何理解实现Callable接口的方式创建多线程,比实现Runable接口创建多线程方式更强大?
11 * 1.call()可以有返回值
12 * 2.call()可以抛出异常,被外面的操作捕获,获取异常的信息
13 * 3.Callable是支持泛型的
14 *
15 *
16 * @Author Tianhao
17 * @create 2021-02-06-11:17
18 */
19
20 //1.创建一个Callable接口的实现类
21 class NumThread implements Callable<Integer> {
22 //2.实现Callable接口的抽象方法call(),将线程需要执行的操作声明在此方法中
23 //call()可以返回值,如果不需要返回值,就return null
24 @Override
25 public Integer call() throws Exception {
26 int sum = 0;
27 for (int i = 1; i <= 100; i++) {
28 // Thread.sleep(1000);
29 if (i%2 ==0) {
30 System.out.println(Thread.currentThread().getName() + "打印:" + i);
31 sum += i;
32 }
33 }
34 return sum;
35 }
36 }
37
38 public class ThreadNew {
39 public static void main(String[] args) {
40 //3.创建Callable实现类对象
41 NumThread numThread = new NumThread();
42 //4.将此Callable实现类对象作为参数传递到FutureTask类的构造器,
43 // 并创建FutureTask对象
44 FutureTask<Integer> futureTask = new FutureTask<>(numThread);
45 //5.创建线程对象
46 //因为FutureTask间接实现了Runnable接口,
47 // 所以其对象可以作为参数传递到Thread类的构造器中,并创建线程对象
48 Thread t = new Thread(futureTask);
49 t.setName("数字线程");
50 //6.启动线程
51 //仍然是调用Thread对象的start方法来启动线程,
52 // 底层实际调用的是Callable实现类的实现方法call()
53 t.start();
54
55 try {
56 //7.获取线程返回值(根据业务需要可选)
57 //因为FuntureTask间接实现了Future接口,
58 //所以可以通过get()获取其构造器参数Callable实现类的call()返回值
59 Integer result = futureTask.get();
60 Thread.currentThread().setName("主线程");
61 System.out.println(Thread.currentThread().getName() + "打印总和:" + result);
62 } catch (InterruptedException e) {
63 e.printStackTrace();
64 } catch (ExecutionException e) {
65 e.printStackTrace();
66 }
67 }
68 }