前言
这篇文章的代码非常简单,代码后的实验要求一定不要忽略,你一定能理解线程池的算法。
如没看过第一章,请先点我跳转
套用代码
打开你的IDE,并新建一个类,将下方代码拷贝:
1import java.lang.reflect.Executable;
2import java.util.concurrent.ExecutorService;
3import java.util.concurrent.Executors;
4
5public class TestThreadPool {
6 ExecutorService executorService = Executors.newFixedThreadPool(2);
7 public static void main(String[] args) {
8 //实例化类
9 TestThreadPool testThreadPool = new TestThreadPool();
10 //调用动态方法
11 testThreadPool.threadPool();
12 }
13
14 public void threadPool() {
15 Thread1 thread1 = new Thread1();
16 Thread2 thread2 = new Thread2();
17 for (int i = 0; i < 3; i++) {
18 System.out.println("线程池已提交:" + i);
19 executorService.execute(thread1);
20 executorService.execute(thread2);
21 }
22 //executorService.shutdown();
23 //executorService.shutdownNow();
24 }
25}
26
27/**
28 * 线程1
29 */
30class Thread1 implements Runnable {
31 @Override
32 public void run() {
33 System.out.println("WORKING ON THREAD 1");
34 try {
35 Thread.sleep(500);
36 } catch (Exception e) {}
37 }
38}
39
40/**
41 * 线程2
42 */
43class Thread2 implements Runnable {
44 @Override
45 public void run() {
46 System.out.println("WORKING ON THREAD 2");
47 try {
48 Thread.sleep(500);
49 } catch (Exception e) {}
50 }
51}
此时有三个类被定义,其中Thread1
和Thread2
为两个线程的定义。
运行项目
现在运行你的项目,运行结果如下:
1线程池已提交:0
2WORKING ON THREAD 1
3线程池已提交:1
4WORKING ON THREAD 2
5线程池已提交:2
6WORKING ON THREAD 1
7WORKING ON THREAD 2
8WORKING ON THREAD 1
9WORKING ON THREAD 2
阅读代码,在threadPool
中我们将线程以execute()
提交到了线程池,而通过for循环可以知道共循环提交了三次线程,其中每次分别提交了两个线程。
关闭线程池
你可能发现了,线程池在执行完毕后程序并没有结束,需要手动结束。
现在,将注释掉的executorService.shutdown()
取消注释,再次运行,你会发现程序在执行线程池后线程池自动进行了自销毁且程序自动关闭。
1线程池已提交:0
2WORKING ON THREAD 1
3线程池已提交:1
4WORKING ON THREAD 2
5线程池已提交:2
6WORKING ON THREAD 1
7WORKING ON THREAD 2
8WORKING ON THREAD 1
9WORKING ON THREAD 2
现在,重新注释掉executorService.shutdown()
,并取消注释executorService.shutdownNow()
,运行程序:
1线程池已提交:0
2线程池已提交:1
3WORKING ON THREAD 1
4线程池已提交:2
5WORKING ON THREAD 2
可以看到的是,线程池在没有执行完毕的情况下就终止了程序的运行。这是因为:
1 executorService.shutdown();
2 executorService.shutdownNow();
shutdown()
方法就像你点击了电脑的“关机”按钮一样,它不会立即关闭,而是等待未执行完毕的任务
全部执行完毕之后才会关闭线程池。
shutdownNow()
方法是无视线程池的状态,强制关闭线程池。
调整线程池大小
在代码的最上方,你可以看到:
1ExecutorService executorService = Executors.newFixedThreadPool(2);
其中,我们将newFixedThreadPool(2)
拆分来看:
线程池集合
newFixedThreadPool()
是Executors(线程池集合)中的一种线程池,在Executors类中共有4种线程池可供选择:
1newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
2newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
4newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
而我们使用的newFixedThreadPool
线程池便是一种定长线程池
,它在运行时有如下特性:
1每次只同时运行指定数量的线程,多出的线程会排队等候,直至前面的线程执行完毕再执行。
定义线程池
再来看2,正如你所料的一样,它表示该线程池每次同时只能运行2个线程
,其它超出的线程必须排队等候
执行完毕。
后语
现在,相信你已经对线程池有了大概的了解了。下一章我们将细说线程池的定义方式。