什么原因使我们不得不使用线程池?
个人认为主要原因是:短时间内需要处理的任务数量很多
使用线程池的好处:
1.减少在创建和销毁线程上所花的时间以及系统资源的开销
2.如不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存
以下是Java自带的几种线程池:
1、newFixedThreadPool 创建一个指定工作线程数量的线程池。
每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。
2、newCachedThreadPool 创建一个可缓存的线程池。
这种类型的线程池特点是:
1).工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE), 这样可灵活的往线程池中添加线程。
2).如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。
3、newSingleThreadExecutor 创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,如果这个线程异常结束,会有另一个取代它,保证顺序执行(我觉得这点是它的特色)。
单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的 。
4、newScheduleThreadPool 创建一个定长的线程池,而且支持定时的以及周期性的任务执行,类似于Timer。
总结:
一.FixedThreadPool是一个典型且优秀的线程池,它具有线程池提高程序效率和节省创建线程时所耗的开销的优点。但在线程池空闲时,即线程池中没有可运行任务时,它不会释放工作线程,还会占用一定的系统资源。
二.CachedThreadPool的特点就是在线程池空闲时,即线程池中没有可运行任务时,它会释放工作线程,从而释放工作线程所占用的资源。但是,但当出现新任务时,又要创建一新的工作线程,又要一定的系统开销。并且,在使用CachedThreadPool时,一定要注意控制任务的数量,否则,由于大量线程同时运行,很有会造成系统瘫痪。
Java线程池 ThreadPoolExecutor使用实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
package com.sondon.mayi.jpool;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class JPoolLearn {
private static int produceTaskSleepTime = 3 ;
private static int produceTaskMaxNumber = 20 ;
public void testThreadPoolExecutor(){
/*
* ThreadPoolExecutor(
* int corePoolSize, //线程池维护线程的最少数量
* int maximumPoolSize, //线程池维护线程的最大数量
* long keepAliveTime, //线程池维护线程所允许的空闲时间
* TimeUnit unit, //线程池维护线程所允许的空闲时间的单位
* BlockingQueue<Runnable> workQueue, //线程池所使用的缓冲队列
* RejectedExecutionHandler handler //线程池对拒绝任务的处理策略 )
*/
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
5,
10,
3,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(10),
new ThreadPoolExecutor.DiscardOldestPolicy()
);
for (int i = 1; i <= produceTaskMaxNumber; i++) {
try {
// 产生一个任务,并将其加入到线程池
String task = "task---" + i;
threadPool.execute(new ThreadPoolTask(task));
System.out.println("activeCount :"+ threadPool.getActiveCount());
// 便于观察,等待一段时间
Thread.sleep(produceTaskSleepTime);
} catch (Exception e) {
e.printStackTrace();
}
}
//查看当前的线程池状况
while(true){
try {
Thread.sleep(3000);
System.out.println("pool size :"+threadPool.getPoolSize());//线程池中线程数量
System.out.println("active count :"+threadPool.getActiveCount());//线程池中活动的线程数量
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
*
* @Author 蔡文锋
* @Data_Time 2015年7月25日 下午4:06:28
* @Description { 测试不同线程池模式 }
*/
public void testNewCachedThreadPool(){
ThreadPoolExecutor threadPool=(ThreadPoolExecutor) Executors.newCachedThreadPool();
// ThreadPoolExecutor threadPool=(ThreadPoolExecutor) Executors.newFixedThreadPool(100);
// ThreadPoolExecutor threadPool=(ThreadPoolExecutor) Executors.newScheduledThreadPool(100);
// ThreadPoolExecutor threadPool=(ThreadPoolExecutor) Executors.newSingleThreadExecutor();
try {
for (int i = 0; i < 100; i++) {
// 产生一个任务,并将其加入到线程池
String task = "task---" + i;
threadPool.execute(new ThreadPoolTask(task));
System.out.println("activeCount :");
// 便于观察,等待一段时间
Thread.sleep(produceTaskSleepTime);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
//查看当前的线程池状况
while(true){
try {
Thread.sleep(3000);
System.out.println("pool size :"+threadPool.getPoolSize());//线程池中线程数量
System.out.println("active count :"+threadPool.getActiveCount());//线程池中活动的线程数量
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
*
* @Author 蔡文锋
* @Data_Time 2015年7月25日 下午4:06:58
* @Description { 测试callable与runable方法的区别 }
*/
public void testNewCachedThreadPool_callable(){
ExecutorService es=Executors.newFixedThreadPool(10);
try {
// String result=es.submit(new MyCallable<String>()).get();
// System.out.println("callable result :"+result);
String result=(String) es.submit(new ThreadPoolTask("")).get();
System.out.println("runable result :"+result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new JPoolLearn().testNewCachedThreadPool();
}
}
/**
* 线程池执行的任务
*/
class ThreadPoolTask implements Runnable {
private static int consumeTaskSleepTime = 2000;
// 保存任务所需要的数据
private Object threadPoolTaskData;
ThreadPoolTask(Object tasks) {
this.threadPoolTaskData = tasks;
}
public void run() {
System.out.println("start .." + threadPoolTaskData);
try {
// Sleep 2秒 模拟耗时操作
Thread.sleep(consumeTaskSleepTime);
} catch (Exception e) {
e.printStackTrace();
}
threadPoolTaskData = null;
}
public Object getTask() {
return this.threadPoolTaskData;
}
}
/**
*
* @Project : JPool
* @Package : com.sondon.mayi.jpool
* @Class : MyCallable
* @param <T>
*/
class MyCallable<T> implements Callable<T>{
@Override
public T call() throws Exception {
System.out.println( "开始执行Callable" );
return (T) "测试callable接口" ;
}
}
|