/**
- 线程池API ->接口定义和实现类:
- 【接口】:Executor : 最上层的接口,定义了执行任务的方法execute
- 【接口】:ExecutorService : 继承了Executor接口,拓展了Callable、Future、关闭方法
- 【接口】:ScheduledExecutorService: 继承了ExecutorService,增加了定时任务相关的方法
- 【实现类】:ThreadPoolExecutor: 基础、标准的线程池实现
- 【实现类】:ScheduledThreadPoolExecutor: 继承了ThreadPoolExecutor,实现了ScheduledExecutorService中相关的定时任务方法
-
- 线程池介绍:
- newFixedThreadPool(int threads): 创建一个固定线程数,任务队列无界的线程池;核心线程数=最大线程数
- newCachedThreadPool():创建一个大小无界的线程池,(mix=0;max=Integer.MAX_VALUE)多少无惧,线程空闲60秒则自动销毁,无任务时线程数为0,适合无法预估需要多少线程场景
- newSingleThreadExecutor():始终只有一个线程处理任务,数量硬编码,不可改变
- newScheduledThreadPool(int corePoolSize):能够定时执行任务的线程池,核心数量由参数指定,MAX=Integer.VALUE
-
- 线程池数量多少为宜?
- 计算型(例如 加减乘除):cpu数量的1-2倍
- IO型:根据实际场景调试:【cpu达到80%,说明cpu已经被充分利用,或大或小自己可以调试线程池数量】
*/
代码如下:
package com.nipeixing.demo.thread;
import java.util.List;
import java.util.concurrent.*;
public class ThreadPool {
public static void main(String[] args) throws Exception {
//new ThreadPool().threadPoolTest1();
//new ThreadPool().threadPoolTest2();
//new ThreadPool().threadPoolTest3();
//new ThreadPool().threadPoolTest4();
//new ThreadPool().threadPoolTest5();
//new ThreadPool().threadPoolTest6();
//new ThreadPool().threadPoolTest7();
//new ThreadPool().threadPoolTest8();
new ThreadPool().threadPoolTest9();
}
private void testThreadPool(ThreadPoolExecutor threadPool) throws Exception {
for (int i = 0; i < 15; i++) {
int n = i;
threadPool.submit(new Runnable() {
@Override
public void run() {
try {
System.out.println("线程" + n + "开始执行");
Thread.sleep(2000L);
System.out.println("线程" + n + "执行结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
System.out.println("任务已提交" + n);
}
Thread.sleep(200L);
System.out.println("查看线程池数量为:" + threadPool.getPoolSize());
System.out.println("查看线程池等待数量为:" + threadPool.getQueue().size());
Thread.sleep(10000L);
System.out.println("等待10s后,查看线程池数量为:" + threadPool.getPoolSize());
System.out.println("等待10s后,查看线程池等待数量为:" + threadPool.getQueue().size());
}
/**
* 第一种:
* 普通线程池,核心数量为5,最大线程数量为10,多出的线程存活时间为5s,队列为无界
*/
public void threadPoolTest1() throws Exception {
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>());
testThreadPool(threadPool);
}
/**
* 第二种:
* 普通线程池,核心数量为5,最大线程数量为10,队列大小为2,多出的线程存活时间为5s,指定一个拒绝策略
*/
public void threadPoolTest2() throws Exception {
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(2), new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println("多出的线程被拒绝");
}
});
testThreadPool(threadPool);
}
/**
* 第三种:
* 普通线程池,核心数量为5,最大线程数量为5,队列无界,多出的线程存活时间为5s
*/
public void threadPoolTest3() throws Exception {
//这种和Executors.newFixedThreadPool(5);是一样的效果
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>());
testThreadPool(threadPool);
}
/**
* 第四种:
* 普通线程池,核心数量为0,最大线程数量为Integer.MAX_VALUE,队列无界,多出的线程存活时间为5s
*/
public void threadPoolTest4() throws Exception {
//这种和Executors.newCachedThreadPool();是一样的效果
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
new SynchronousQueue<>());
testThreadPool(threadPool);
Thread.sleep(60000L);
System.out.println("等待60s后线程池的数量应该为0?:---->" + threadPool.getPoolSize());
}
/**
* 第五种:
* 定时任务线程池,5s后执行
* 核心线程数为5,最大线程数为Integer.MAX_VALUE ,DelayedWorkQueue延迟队列,超出核心线程数的存活时间为0s
*/
public void threadPoolTest5() {
//这种和 Executors.newScheduledThreadPool(5);是一样的效果
ScheduledThreadPoolExecutor threadPool = new ScheduledThreadPoolExecutor(5);
threadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println("任务被执行,现在执行时间为" + System.currentTimeMillis());
}
}, 5000, TimeUnit.MILLISECONDS);
System.out.println("定时任务提交时间为" + System.currentTimeMillis() + "线程池中线程数量为:" + threadPool.getPoolSize());
}
/**
* 第六种:
* 定时任务线程池,2s后执行一次,之后每隔2秒,任务执行一次,因此任务需要4秒执行一次
* 不会并发执行,一个一个,等待上个任务执行完之后,再执行下一个
*/
public void threadPoolTest6() {
ScheduledThreadPoolExecutor threadPool = new ScheduledThreadPoolExecutor(5);
threadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(4000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务被执行,现在执行时间为" + System.currentTimeMillis());
}
}, 2000, 2000, TimeUnit.MILLISECONDS);
}
/**
* 第七种:
* 定时任务线程池,2s后执行一次,之后每隔2秒,任务执行一次,因此任务需要4秒执行一次
* 不会并发执行,一个一个,等待上个任务执行完之后,再执行下一个
* 但是,如果任务执行了3秒,这个时候就按3s执行一次,之后每隔2秒,任务执行一次,
* 所以【实际执行时间=任务需要任务执行时间+间隔时间】
*/
public void threadPoolTest7() {
ScheduledThreadPoolExecutor threadPool = new ScheduledThreadPoolExecutor(5);
threadPool.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务被执行,现在执行时间为" + System.currentTimeMillis());
}
}, 2000, 1000, TimeUnit.MILLISECONDS);
}
/**
* 第八种: 终止线程池,核心线程5,最大线程数10,队列为2,多出线程5s存活时间,
* 此方法终止线程池之后,已经启动的线程会执行完毕
* 之后再提交的线程,不会被执行
*/
public void threadPoolTest8() throws InterruptedException {
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(2), new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println("多出的线程被拒绝");
}
});
for (int i = 0; i < 15; i++) {
threadPool.submit(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
System.out.println("任务提交成功" + i);
}
Thread.sleep(1000L);
threadPool.shutdown();
threadPool.submit(new Runnable() {
@Override
public void run() {
System.out.println("线程关闭之后追加一个任务");
}
});
}
/**
* 第九种: 终止线程池,核心线程5,最大线程数10,队列为2,多出线程5s存活时间
* 此方法终止线程池之后,已经执行任务的线程会立即停止(interrupted方法),未执行任务的线程会被拒绝
* 等待中的线程,会返回所有的任务信息【List<Runnable> runnables = threadPool.shutdownNow();】
*/
public void threadPoolTest9() throws InterruptedException {
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(2), new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println("多出的线程被拒绝");
}
});
for (int i = 0; i < 15; i++) {
threadPool.submit(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
System.out.println("任务提交成功" + i);
}
Thread.sleep(1000L);
List<Runnable> runnables = threadPool.shutdownNow();
threadPool.submit(new Runnable() {
@Override
public void run() {
System.out.println("线程关闭之后追加一个任务");
}
});
System.out.println("未执行的线程的信息数量为:" + runnables.size() + "个");
}
}