Java 线程池 四种创建方式
dong4j 2/5/2016
JavaSE
Concurrent
总结线程池的使用方式
Java通过Executors提供四种线程池, 分别为:
- newCachedThreadPool创建一个可缓存线程池, 如果线程池长度超过处理需要, 可灵活回收空闲线程, 若无可回收, 则新建线程.
- newFixedThreadPool 创建一个定长线程池, 可控制线程最大并发数, 超出的线程会在队列中等待.
- newScheduledThreadPool 创建一个定长线程池, 支持定时及周期性任务执行.
- newSingleThreadExecutor 创建一个单线程化的线程池, 它只会用唯一的工作线程来执行任务, 保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行.
线程池比较单线程的优势在于:
- 重用存在的线程, 减少对象创建、消亡的开销, 性能佳.
- 可有效控制最大并发线程数, 提高系统资源的使用率, 同时避免过多资源竞争, 避免堵塞.
- 提供定时执行、定期执行、单线程、并发数控制等功能.
newCachedThreadPool
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
cachedThreadPool.execute(new Runnable() {
public void run() {
System.out.println(index);
}
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
1
2
3
4
5
2
3
4
5
创建一个可缓存线程池, 如果线程池长度超过处理需要, 可灵活回收空闲线程, 若无可回收, 则新建线程.
这里的线程池是无限大的, 当一个线程完成任务之后, 这个线程可以接下来完成将要分配的任务, 而不是创建一个新的线程,
java api 1.7 will reuse previously constructed threads when they are available.
newFixedThreadPool
public static void main(String[] args) {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int index = i;
fixedThreadPool.execute(new Runnable() {
public void run() {
try {
System.out.println(index);
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
1
2
3
4
5
2
3
4
5
创建一个定长线程池, 可控制线程最大并发数, 超出的线程会在队列中等待
定长线程池的大小最好根据系统资源进行设置. 如Runtime.getRuntime().availableProcessors()
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
for (int i = 0; i < 10; i++) {
scheduledThreadPool.schedule(new Runnable() {
public void run() {
System.out.println("delay 3 seconds");
}
}, 3, TimeUnit.SECONDS);
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
newSingleThreadExecutor
public static void main(String[] args) {
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int index = i;
singleThreadExecutor.execute(new Runnable() {
public void run() {
/* System.out.println(index);*/
try {
System.out.println(index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
1
2
3
4
5
6
2
3
4
5
6
按顺序来执行线程任务 但是不同于单线程, 这个线程池只是只能存在一个线程, 这个线程死后另外一个线程会补上
/**
* ThreadPoolExecutor类的使用方法
* 实现高并发: 在线程类中的run()方法内设置Thread.sleep(long delta); delta取值为: (并发开始时间戳 - 线程开始时间戳)
* Created by Administrator on 2016/11/19.
*/
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
//设置核心池大小
int corePoolSize = 5;
//设置线程池最大能接受多少线程
//当前线程数大于corePoolSize、小于maximumPoolSize时, 超出corePoolSize的线程数的生命周期
long keepActiveTime = 200;
//设置时间单位, 秒
TimeUnit timeUnit = TimeUnit.SECONDS;
//设置线程池缓存队列的排队策略为FIFO, 并且指定缓存队列大小为5
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(5);
//创建ThreadPoolExecutor线程池对象, 并初始化该对象的各种参数
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepActiveTime, timeUnit,workQueue);
//往线程池中循环提交线程
for (int i = 0; i < 15; i++) {
//创建线程类对象
MyTask myTask = new MyTask(i);
//开启线程
executor.execute(myTask);
//获取线程池中线程的相应参数
System.out.println("线程池中线程数目: " +executor.getPoolSize() + ", 队列中等待执行的任务数目: "+executor.getQueue().size() + ", 已执行完的任务数目: "+executor.getCompletedTaskCount());
}
//待线程池以及缓存队列中所有的线程任务完成后关闭线程池.
executor.shutdown();
}
}
/**
*线程类
*/
class MyTask implements Runnable {
private int num;
public MyTask(int num) {
this.num = num;
}
@Override
public void run() {
System.out.println("正在执行task " + num );
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task " + num + "执行完毕");
}
/**
* 获取(未来时间戳-当前时间戳)的差值,
* 也即是: (每个线程的睡醒时间戳-每个线程的入睡时间戳)
* 作用: 用于实现多线程高并发
* @return
* @throws ParseException
*/
public long getDelta() throws ParseException {
//获取当前时间戳
long t1 = new Date().getTime();
//获取未来某个时间戳(自定义, 可写入配置文件)
String str = "2016-11-11 15:15:15";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
long t2 = simpleDateFormat.parse(str).getTime();
return t2 - t1;
}
}
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
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