JDK1.8 创建线程池有哪几种方式?
- newFixedThreadPool
定长线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程数量不再变化,当线程发生错误结束时,线程池会补充一个新的线程
测试代码:
代码语言:javascript复制public class TestThreadPool {
//定长线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程数量不再变化,当线程发生错误结束时,线程池会补充一个新的线程
static ExecutorService fixedExecutor = Executors.newFixedThreadPool(3);
public static void main(String[] args) {
testFixedExecutor();
}
//测试定长线程池,线程池的容量为3,提交6个任务,根据打印结果可以看出先执行前3个任务,3个任务结束后再执行后面的任务
private static void testFixedExecutor() {
for (int i = 0; i < 6; i ) {
final int index = i;
fixedExecutor.execute(new Runnable() {
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() " index:" index);
}
});
}
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("4秒后...");
fixedExecutor.shutdown();
}
}
打印结果:
代码语言:javascript复制pool-1-thread-1 index:0
pool-1-thread-2 index:1
pool-1-thread-3 index:2
4秒后...
pool-1-thread-3 index:5
pool-1-thread-1 index:3
pool-1-thread-2 index:4
- newCachedThreadPool
可缓存的线程池,如果线程池的容量超过了任务数,自动回收空闲线程,任务增加时可以自动添加新线程,线程池的容量不限制
测试代码:
代码语言:javascript复制public class TestThreadPool {
//可缓存的线程池,如果线程池的容量超过了任务数,自动回收空闲线程,任务增加时可以自动添加新线程,线程池的容量不限制
static ExecutorService cachedExecutor = Executors.newCachedThreadPool();
public static void main(String[] args) {
testCachedExecutor();
}
//测试可缓存线程池
private static void testCachedExecutor() {
for (int i = 0; i < 6; i ) {
final int index = i;
cachedExecutor.execute(new Runnable() {
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() " index:" index);
}
});
}
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("4秒后...");
cachedExecutor.shutdown();
}
}
打印结果:
代码语言:javascript复制pool-1-thread-1 index:0
pool-1-thread-6 index:5
pool-1-thread-5 index:4
pool-1-thread-4 index:3
pool-1-thread-3 index:2
pool-1-thread-2 index:1
4秒后...
- newScheduledThreadPool 定长线程池,可执行周期性的任务
测试代码:
代码语言:javascript复制public class TestThreadPool {
//定长线程池,可执行周期性的任务
static ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(3);
public static void main(String[] args) {
testScheduledExecutor();
}
//测试定长、可周期执行的线程池
private static void testScheduledExecutor() {
for (int i = 0; i < 3; i ) {
final int index = i;
//scheduleWithFixedDelay 固定的延迟时间执行任务;scheduleAtFixedRate 固定的频率执行任务
scheduledExecutor.scheduleWithFixedDelay(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName() " index:" index);
}
}, 0, 3, TimeUnit.SECONDS);
}
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("4秒后...");
scheduledExecutor.shutdown();
}
}
打印结果:
代码语言:javascript复制pool-1-thread-1 index:0
pool-1-thread-2 index:1
pool-1-thread-3 index:2
pool-1-thread-1 index:0
pool-1-thread-3 index:1
pool-1-thread-1 index:2
4秒后...
- newSingleThreadExecutor
单线程的线程池,线程异常结束,会创建一个新的线程,能确保任务按提交顺序执行
测试代码:
代码语言:javascript复制public class TestThreadPool {
//单线程的线程池,线程异常结束,会创建一个新的线程,能确保任务按提交顺序执行
static ExecutorService singleExecutor = Executors.newSingleThreadExecutor();
public static void main(String[] args) {
testSingleExecutor();
}
//测试单线程的线程池
private static void testSingleExecutor() {
for (int i = 0; i < 3; i ) {
final int index = i;
singleExecutor.execute(new Runnable() {
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() " index:" index);
}
});
}
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("4秒后...");
singleExecutor.shutdown();
}
}
打印结果:
代码语言:javascript复制pool-1-thread-1 index:0
4秒后...
pool-1-thread-1 index:1
pool-1-thread-1 index:2
- newSingleThreadScheduledExecutor
单线程可执行周期性任务的线程池
测试代码:
代码语言:javascript复制public class TestThreadPool {
//单线程可执行周期性任务的线程池
static ScheduledExecutorService singleScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
public static void main(String[] args) {
testSingleScheduledExecutor();
}
//测试单线程可周期执行的线程池
private static void testSingleScheduledExecutor() {
for (int i = 0; i < 3; i ) {
final int index = i;
//scheduleWithFixedDelay 固定的延迟时间执行任务;scheduleAtFixedRate 固定的频率执行任务
singleScheduledExecutor.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName() " index:" index);
}
}, 0, 3, TimeUnit.SECONDS);
}
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("4秒后...");
singleScheduledExecutor.shutdown();
}
}
打印结果:
代码语言:javascript复制pool-1-thread-1 index:0
pool-1-thread-1 index:1
pool-1-thread-1 index:2
pool-1-thread-1 index:0
pool-1-thread-1 index:1
pool-1-thread-1 index:2
4秒后...
- newWorkStealingPool
任务窃取线程池,不保证执行顺序,适合任务耗时差异较大。
线程池中有多个线程队列,有的线程队列中有大量的比较耗时的任务堆积,而有的线程队列却是空的,就存在有的线程处于饥饿状态,当一个线程处于饥饿状态时,它就会去其它的线程队列中窃取任务。解决饥饿导致的效率问题。
默认创建的并行 level 是 CPU 的核数。主线程结束,即使线程池有任务也会立即停止。
测试代码:
代码语言:javascript复制public class TestThreadPool {
//任务窃取线程池
static ExecutorService workStealingExecutor = Executors.newWorkStealingPool();
public static void main(String[] args) {
testWorkStealingExecutor();
}
//测试任务窃取线程池
private static void testWorkStealingExecutor() {
for (int i = 0; i < 10; i ) {//本机 CPU 8核,这里创建10个任务进行测试
final int index = i;
workStealingExecutor.execute(new Runnable() {
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() " index:" index);
}
});
}
try {
Thread.sleep(4000);//这里主线程不休眠,不会有打印输出
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("4秒后...");
// workStealingExecutor.shutdown();
}
}
打印结果如下,index:8,index:9并未打印出:
代码语言:javascript复制ForkJoinPool-1-worker-1 index:0
ForkJoinPool-1-worker-7 index:6
ForkJoinPool-1-worker-5 index:4
ForkJoinPool-1-worker-3 index:2
ForkJoinPool-1-worker-4 index:3
ForkJoinPool-1-worker-2 index:1
ForkJoinPool-1-worker-0 index:7
ForkJoinPool-1-worker-6 index:5
4秒后...