1 概述

池化是常见的思想,线程池是非常典型的池化的实现,《Java并发编程实战》也大篇幅去讲解了Java中的线程池。本文实现一个简单的线程池。

2 核心类

【1】接口定义


[java]  view plain  copy


print 
   ? 
    
    
 
1. public interface IThreadPool<Job extends Runnable> {  
2. /**
3.      * 关闭线程池
4.      */  
5. public void shutAlldown();  
6.   
7. /**
8.      * 执行任务
9.      * 
10.      * @param job 任务
11.      */  
12. public void execute(Job job);  
13.   
14. /**
15.      * 添加工作者
16.      * 
17.      * @param addNum 添加数
18.      */  
19. public void addWorkers(int addNum);  
20.   
21. /**
22.      * 减少工作者
23.      * 
24.      * @param reduceNum 减少数目
25.      */  
26. public void reduceWorkers(int reduceNum);  
27. }


【2】实现类

1个任务列表和1个工作者列表。


[java]  view plain  copy


 print ?

1. import java.util.ArrayList;  
2. import java.util.Collections;  
3. import java.util.LinkedList;  
4. import java.util.List;  
5.   
6. public class XYThreadPool<Job extends Runnable> implements IThreadPool<Job> {  
7.   
8. // 默认线程数  
9. private static int DEAFAULT_SIZE = 5;  
10. // 最大线程数  
11. private static int MAX_SIZE = 10;  
12.   
13. // 任务列表  
14. private LinkedList<Job> tasks = new LinkedList<Job>();  
15. // 工作线程列表  
16. private List<Worker> workers = Collections  
17. new ArrayList<Worker>());  
18.   
19. /**
20.      * 默认构造函数
21.      */  
22. public XYThreadPool() {  
23.         initWokers(DEAFAULT_SIZE);  
24.     }  
25.   
26. /**
27.      * 执行线程数
28.      * 
29.      * @param threadNums 线程数
30.      */  
31. public XYThreadPool(int workerNum) {  
32. 0 ? DEAFAULT_SIZE  
33.                 : workerNum > MAX_SIZE ? MAX_SIZE : workerNum;  
34.         initWokers(workerNum);  
35.     }  
36.   
37. /**
38.      * 初始化线程池
39.      * 
40.      * @param threadNums 线程数
41.      */  
42. public void initWokers(int threadNums) {  
43. for (int i = 0; i < threadNums; i++) {  
44. new Worker();  
45.             worker.start();  
46.             workers.add(worker);  
47.         }  
48. // 添加关闭钩子  
49. new Thread() {  
50. public void run() {  
51.                 shutAlldown();  
52.             }  
53.         });  
54.     }  
55.   
56. @Override  
57. public void shutAlldown() {  
58. for (Worker worker : workers) {  
59.             worker.shutdown();  
60.         }  
61.     }  
62.   
63. @Override  
64. public void execute(Job job) {  
65. synchronized (tasks) {  
66. // 提交任务就是将任务对象加入任务队列,等待工作线程去处理  
67.             tasks.addLast(job);  
68.             tasks.notifyAll();  
69.         }  
70.     }  
71.   
72. @Override  
73. public void addWorkers(int addNum) {  
74. // 新线程数必须大于零,并且线程总数不能大于最大线程数  
75. if ((workers.size() + addNum) <= MAX_SIZE && addNum > 0) {  
76.             initWokers(addNum);  
77. else {  
78. "addNum too large");  
79.         }  
80.     }  
81.   
82. @Override  
83. public void reduceWorkers(int reduceNum) {  
84. if ((workers.size() - reduceNum <= 0))  
85. "thread num too small");  
86. else {  
87. // 暂停指定数量的工作者  
88. int count = 0;  
89. while (count != reduceNum) {  
90. for (Worker w : workers) {  
91.                     w.shutdown();  
92.                     count++;  
93.                 }  
94.             }  
95.         }  
96.     }  
97.   
98. /**
99.      * 工作线程
100.      */  
101. class Worker extends Thread {  
102.   
103. private volatile boolean flag = true;  
104.   
105. @Override  
106. public void run() {  
107. while (flag) {  
108. null;  
109. // 加锁(若只有一个woker可不必加锁,那就是所谓的单线程的线程池,线程安全)  
110. synchronized (tasks) {  
111. // 任务队列为空  
112. while (tasks.isEmpty()) {  
113. try {  
114. // 阻塞,放弃对象锁,等待被notify唤醒  
115.                             tasks.wait();  
116. "block when tasks is empty");  
117. catch (InterruptedException e) {  
118.                             e.printStackTrace();  
119.                         }  
120.                     }  
121. // 不为空取出任务  
122.                     job = tasks.removeFirst();  
123. "get job:" + job + ",do biz");  
124.                     job.run();  
125.                 }  
126.             }  
127.         }  
128.   
129. public void shutdown() {  
130. false;  
131.         }  
132.     }  
133. }



放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备


2 Object的方法:void notify(): 唤醒一个正在等待该对象的线程。void notifyAll(): 唤醒所有正在等待该对象的线程。notifyAll使所有原来在该对象上等待被notify的线程统统退出wait状态,变成等待该对象上的锁,一旦该对象被解锁,它们会去竞争。notify只是选择一个wait状态线程进行通知,并使它获得该对象上的锁,但不惊动其它同样在等待被该对象notify的线程们,当第一个线程运行完毕以后释放对象上的锁,此时如果该对象没有再次使用notify语句,即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,继续处在wait状态,直到这个对象发出一个notify或notifyAll,它们等待的是被notify或notifyAll,而不是锁。



3 无需控制线程总数

每调用一次就会创建一个拥有10个线程工作者的线程池。


[java]  view plain  copy


print 
   ? 
    
    
 
1. public class TestService1 {  
2. public static void main(String[] args) {  
3. // 启动10个线程  
4. new XYThreadPool<Runnable>(10);  
5. new Runnable() {  
6. @Override  
7. public void run() {  
8. "====1 test====");  
9.             }  
10.         });   
11.     }  
12. }  
13.   
14. public class TestService2 {  
15. public static void main(String[] args) {  
16. // 启动10个线程  
17. new XYThreadPool<Runnable>(10);  
18. new Runnable() {  
19. @Override  
20. public void run() {  
21. "====2 test====");  
22.             }  
23.         });  
24.     }  
25. }





4 控制线程总数

希望在项目中所有的线程调用,都共用1个固定工作者数大小的线程池。


[java]  view plain  copy


print 
   ? 
    
    
 
1. import javax.annotation.PostConstruct;  
2. import org.springframework.stereotype.Component;  
3. import com.xy.pool.XYThreadPool;  
4.   
5. /**
6.  * 统一线程池管理类 
7.  */  
8. @Component  
9. public class XYThreadManager {  
10.   
11. private XYThreadPool<Runnable> executorPool;  
12.   
13. @PostConstruct  
14. public void init() {  
15. new XYThreadPool<Runnable>(10);  
16.     }  
17.   
18. public XYThreadPool<Runnable> getExecutorPool() {  
19. return executorPool;  
20.     }  
21. }  
22.   
23. import org.springframework.beans.factory.annotation.Autowired;  
24. import org.springframework.stereotype.Service;  
25.   
26. @Service("testService3")  
27. public class TestService3 {  
28.       
29. @Autowired  
30. private XYThreadManager threadManager;  
31.       
32. public void test() {  
33. new Runnable() {  
34. @Override  
35. public void run() {  
36. "====3 test====");  
37.             }  
38.         });  
39.     }  
40. }  
41.   
42. import org.springframework.beans.factory.annotation.Autowired;  
43. import org.springframework.stereotype.Service;  
44.   
45. @Service("testService4")  
46. public class TestService4 {  
47.       
48. @Autowired  
49. private XYThreadManager threadManager;  
50.       
51. public void test() {  
52. new Runnable() {  
53. @Override  
54. public void run() {  
55. "====4 test====");  
56.             }  
57.         });  
58.     }  
59. }  
60.   
61. import org.springframework.context.ApplicationContext;  
62. import org.springframework.context.support.ClassPathXmlApplicationContext;  
63.   
64. public class TestMain {  
65.   
66. @SuppressWarnings("resource")  
67. public static void main(String[] args) {  
68. new ClassPathXmlApplicationContext("applicationContext.xml");  
69.   
70. "testService3");  
71.         t3.test();  
72.   
73. "testService4");  
74.         t4.test();  
75.     }  
76.   
77. }