Java 线程池示例
一、任务类 HapdayTask4_Thread:
1 package com.javabase.V18.concurrent.pool;
2
3 import java.util.Calendar;
4 import java.util.Random;
5 import java.util.concurrent.Callable;
6
7 /**
8 * <p>任务是由线程承载的,具体来说是由线程类的具体方法来体现的,实际上这里的任务就是线程;<p/>
9 * <p>线程本身就是一个对象,与普通对象最大的不同是可以运行,属于指令类数据。</p>
10 * <p>POJO 纯粹属于只承载参数的数据,POJO 可以翻译为朴素的、简单的 Java 对象。</p>
11 * <p>数据主要分为两类:一类是参数型数据;另一类是指令型数据。它们的关系是根据指令型数据操作参数型数据以完成特定的业务逻辑,即外在表现为实现某种功能。</p>
12 */
13 public class HapdayTask4_Thread implements Callable<String> {
14
15 private int number;
16 private long sleepTime;
17
18 public HapdayTask4_Thread(int number, long sleepTime) {
19 this.number = number;
20 this.sleepTime = sleepTime;
21 }
22
23 @Override
24 public String toString() {
25 return "Hapday_Thread{number=" + number + '}';
26 }
27
28 private long processCommand () {
29 try {
30 Thread.sleep(this.sleepTime); // 模拟执行任务的用时
31 } catch (InterruptedException e) {
32 System.out.println("\033[33;1m 第 " + this.number + " 个线程被终止! \033[0m");
33
34 e.printStackTrace();
35 }
36
37 return sleepTime;
38 }
39
40 private String getCurrentTime () {
41 Calendar calendar = Calendar.getInstance();
42
43 String currentTime = calendar.get(Calendar.YEAR)
44 + "-".concat( String.valueOf( 10 < (calendar.get(Calendar.MONDAY) + 1) ? (calendar.get(Calendar.MONDAY) + 1) : "0" + (calendar.get(Calendar.MONDAY) + 1) ) )
45 + "-".concat ( 10 < calendar.get(Calendar.DAY_OF_MONTH) ? String.valueOf(calendar.get(Calendar.DAY_OF_MONTH)) : "0" + calendar.get(Calendar.DAY_OF_MONTH) )
46 + " " + ( 10 < calendar.get(Calendar.HOUR) ? calendar.get(Calendar.HOUR) : "0" + calendar.get(Calendar.HOUR) )
47 + ":" + ( 10 < calendar.get(Calendar.MINUTE) ? calendar.get(Calendar.MINUTE) : "0" + calendar.get(Calendar.MINUTE) )
48 + ":" + ( 10 < calendar.get(Calendar.SECOND) ? calendar.get(Calendar.SECOND) : "0" + calendar.get(Calendar.SECOND) )
49 + "." + calendar.get(Calendar.MILLISECOND);
50
51 return currentTime;
52 }
53
54 @Override
55 public String call() throws Exception {
56 String currentThreadName = Thread.currentThread().getName();
57 System.out.println("\033[35;2m".concat("时间 ").concat(this.getCurrentTime()).concat(" 开始执行第 ") + this.number + " 个任务 ".concat(currentThreadName).concat( "\033[0m"));
58 long duration = this.processCommand(); // 用时
59 System.out.println("\033[34;3m".concat("时间 ").concat(this.getCurrentTime()).concat(" 结束执行第 ") + this.number + " 个任务 ".concat(currentThreadName).concat(" 用时 " + duration + " 毫秒").concat( "\033[0m"));
60
61 String result = "线程 ".concat(currentThreadName).concat(" 执行成功,用时 ").concat(duration + " 毫秒");
62 return result;
63 }
64 }
2、线程池测试类 ThreadPoolExecutor11_Test:
1 package com.javabase.V18.concurrent.pool;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.concurrent.*;
6
7 public class ThreadPoolExecutor11_Test {
8
9 private static final int CORE_THREAD_QUANTITY = 8; // 核心线程数
10 private static final int MAX_THREAD_QUANTITY = 16; // 最大线程数
11 private static final int TASK_QUEUE_CAPACITY = 100; // 任务队列容量
12 private static final long KEEP_ALIVE_TIME = 10; // 存活时间
13
14 /**
15 * 这个主(main)方法也是一个线程,其建立与虚拟机的联系经过了很多步骤;
16 * 主线程采用套接字接口通过 TCP 协议建立与虚拟机的联系。
17 * @param args
18 */
19 public static void main(String[] args) {
20
21 long beginTime = System.currentTimeMillis();
22 System.out.println("\033[34;1m 开始时间 = " + beginTime + "\033[0m");
23
24 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(CORE_THREAD_QUANTITY
25 , MAX_THREAD_QUANTITY
26 , KEEP_ALIVE_TIME
27 , TimeUnit.SECONDS
28 , new ArrayBlockingQueue<>(TASK_QUEUE_CAPACITY)
29 , new ThreadPoolExecutor.CallerRunsPolicy()
30 ); // 实例化线程池执行器类
31
32 System.out.println("多线程执行任务 - 开始");
33 int taskQuantity = 500; // 任务数,当任务数超过了任务队列的容量后会创建非核心线程,否则完全由核心线程消化掉这些线程
34 long duration = taskQuantity;
35 List<Future<String>> hapday_future_list = new ArrayList<>();
36 for ( int index = 0; index < taskQuantity; index++) {
37 duration -= 1; // 休眠时长每次递减 1 毫秒
38
39 Callable<String> hapdayTask = new HapdayTask4_Thread(index + 1, duration); // 创建任务
40 Future<String> hapday_future = threadPoolExecutor.submit(hapdayTask); // 提交任务,这是个异步方法,会调用“执行(execute)”方法
41 System.out.println("\033[33;1m threadPoolMonitor = " + threadPoolExecutor + "\033[0m");
42
43 hapday_future_list.add(hapday_future);
44 }
45 System.out.println("多线程执行任务 - 结束");
46
47 for ( Future hapday_future : hapday_future_list) {
48 try {
49 System.out.println("\033[36;1m" + "执行结果:" + hapday_future.get() + "\033[0m"); // “获取(get)”方法会阻塞后续线程的执行,直到当前线程执行完毕才会进入执行
50 } catch (InterruptedException e) {
51 e.printStackTrace();
52 } catch (ExecutionException e) {
53 e.printStackTrace();
54 }
55 }
56 System.out.println("\033[33;1m 0 秒后 threadPoolMonitor = " + threadPoolExecutor + "\033[0m");
57
58 long endTime = System.currentTimeMillis();
59 long sumTime = endTime - beginTime;
60 System.out.println("\033[34;1m 用时 " + sumTime + " 毫秒 = " + sumTime / 1000 + " 秒 \033[0m");
61
62 long delay = KEEP_ALIVE_TIME * 1000 - 1000; // 延时 9 秒中,未超过“存活时长”
63 try {
64 Thread.sleep(delay);
65 } catch (InterruptedException e) {
66 e.printStackTrace();
67 }
68 System.out.println("\033[33;1m " + delay / 1000 + " 秒后 threadPoolMonitor = " + threadPoolExecutor + "\033[0m");
69
70 delay = KEEP_ALIVE_TIME * 1000 + 1000; // 延时 11 秒中,已超过“存活时长”,“非核心线程”被回收,如有新超过队列容量的任务过来后再创建
71 try {
72 Thread.sleep(delay);
73 } catch (InterruptedException e) {
74 e.printStackTrace();
75 }
76 System.out.println("\033[33;1m " + delay / 1000 + " 秒后 threadPoolMonitor = " + threadPoolExecutor + "\033[0m");
77
78 delay = 5000; // 修整 5 秒以便观察
79 try {
80 Thread.sleep(delay);
81 } catch (InterruptedException e) {
82 e.printStackTrace();
83 }
84 System.out.println("\033[33;1m " + delay / 1000 + " 秒后 threadPoolMonitor = " + threadPoolExecutor + "\033[0m");
85
86 System.out.println("再来一拨任务 - 开始");
87 taskQuantity = 500; // 任务数,当任务数超过了任务队列的容量后会创建非核心线程,否则完全由核心线程消化掉这些线程
88 duration = taskQuantity;
89 System.out.println("\033[33;1m 清空前 = " + hapday_future_list.size() + "\033[0m");
90 hapday_future_list.clear(); // 清空
91 System.out.println("\033[33;1m 清空后 = " + hapday_future_list.size() + "\033[0m");
92 for ( int index = 0; index < taskQuantity; index++) {
93 duration -= 1; // 休眠时长每次递减 1 毫秒
94
95 Callable<String> hapdayTask = new HapdayTask4_Thread(index + 1, duration); // 创建任务
96 Future<String> hapday_future = threadPoolExecutor.submit(hapdayTask); // 提交任务,这是个异步方法,会调用“执行(execute)”方法
97 System.out.println("\033[33;1m threadPoolMonitor = " + threadPoolExecutor + "\033[0m");
98
99 hapday_future_list.add(hapday_future);
100 }
101 System.out.println("再来一拨任务 - 结束");
102
103 for ( Future hapday_future : hapday_future_list) {
104 try {
105 System.out.println("\033[36;1m" + "执行结果:" + hapday_future.get() + "\033[0m"); // “获取(get)”方法会阻塞后续线程的执行,直到当前线程执行完毕才会进入执行
106 } catch (InterruptedException e) {
107 e.printStackTrace();
108 } catch (ExecutionException e) {
109 e.printStackTrace();
110 }
111 }
112 System.out.println("\033[33;1m 0 秒后 threadPoolMonitor = " + threadPoolExecutor + "\033[0m");
113
114 endTime = System.currentTimeMillis();
115 sumTime = endTime - beginTime;
116 System.out.println("\033[34;1m 用时 " + sumTime + " 毫秒 = " + sumTime / 1000 + " 秒 \033[0m");
117
118 delay = KEEP_ALIVE_TIME * 1000 - 1000; // 延时 9 秒中,未超过“存活时长”
119 try {
120 Thread.sleep(delay);
121 } catch (InterruptedException e) {
122 e.printStackTrace();
123 }
124 System.out.println("\033[33;1m " + delay / 1000 + " 秒后 threadPoolMonitor = " + threadPoolExecutor + "\033[0m");
125
126 delay = KEEP_ALIVE_TIME * 1000 + 1000; // 延时 11 秒中,已超过“存活时长”,“非核心线程”被回收,如有新超过队列容量的任务过来后再创建
127 try {
128 Thread.sleep(delay);
129 } catch (InterruptedException e) {
130 e.printStackTrace();
131 }
132 System.out.println("\033[33;1m " + delay / 1000 + " 秒后 threadPoolMonitor = " + threadPoolExecutor + "\033[0m");
133
134 delay = 5000; // 修整 5 秒以便观察
135 try {
136 Thread.sleep(delay);
137 } catch (InterruptedException e) {
138 e.printStackTrace();
139 }
140 System.out.println("\033[33;1m " + delay / 1000 + " 秒后 threadPoolMonitor = " + threadPoolExecutor + "\033[0m");
141
142 threadPoolExecutor.shutdown(); // 关闭线程池
143
144 }
145
146 }