线程池的作用
可以避免创建、销毁线程带来的性能损耗;可以有效控制并发,避免高并发抢占系统资源导致阻塞;可以对线程进行统一的管理。
实现线程池
java内部实现了四种线程池:
1.newCachedThreadPool创建一个可缓存线程池程
2.newFixedThreadPool 创建一个定长线程池
3.newScheduledThreadPool 创建一个定长线程池
4.newSingleThreadExecutor 创建一个单线程化的线程池
除了这四种以外,我们也可以自定义线程池,满足我们自己的业务需要
自定义线程池
线程处理逻辑
public class MyTask implements Runnable {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public MyTask(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public void run() {
System.out.println("id:" + id + ",name:" + name);
try {
//模拟实现业务,线程睡眠2秒钟
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
拒绝策略
拒绝策略需要实现RejectedExecutionHandler接口,这个接口只有一个方法rejectedExecution,在此方法里面做具体的拒绝处理逻辑,比如发送邮件,短信通知等
public class MyRejected implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
MyTask task = (MyTask) r;
//模拟业务逻辑处理
System.out.println("警告:" + task.getName() + " 被拒绝执行,已经向负责人发送了短信");
}
}
测试类
public class Test2 {
public static void main(String[] args) {
// 自定义一个线程池
ThreadPoolExecutor pool = new ThreadPoolExecutor(
// coreSize 为1
1,
// maxSize 为2
2,
// 等待时间为60秒
60,
TimeUnit.SECONDS,
// 有界队列,容量是2个
new ArrayBlockingQueue<>(2)
//线程工厂
, Executors.defaultThreadFactory()
//超出队列的自定义拒绝策略
, new MyRejected()
);
//逻辑是往线程池添加6个任务,但是线程池的最大数量为2,队列是2,所以会有两个任务被拒绝执行
pool.execute(new MyTask(1, "任务1"));
System.out.println("活跃的线程数:" + pool.getActiveCount() + ",核心线程数:" + pool.getCorePoolSize() + ",线程池大小:" + pool.getPoolSize() + ",队列的大小" + pool.getQueue().size());
pool.execute(new MyTask(2, "任务2"));
System.out.println("活跃的线程数:" + pool.getActiveCount() + ",核心线程数:" + pool.getCorePoolSize() + ",线程池大小:" + pool.getPoolSize() + ",队列的大小" + pool.getQueue().size());
pool.execute(new MyTask(3, "任务3"));
System.out.println("活跃的线程数:" + pool.getActiveCount() + ",核心线程数:" + pool.getCorePoolSize() + ",线程池大小:" + pool.getPoolSize() + ",队列的大小" + pool.getQueue().size());
pool.execute(new MyTask(4, "任务4"));
System.out.println("活跃的线程数:" + pool.getActiveCount() + ",核心线程数:" + pool.getCorePoolSize() + ",线程池大小:" + pool.getPoolSize() + ",队列的大小" + pool.getQueue().size());
pool.execute(new MyTask(5, "任务5"));
System.out.println("活跃的线程数:" + pool.getActiveCount() + ",核心线程数:" + pool.getCorePoolSize() + ",线程池大小:" + pool.getPoolSize() + ",队列的大小" + pool.getQueue().size());
pool.execute(new MyTask(6, "任务6"));
System.out.println("活跃的线程数:" + pool.getActiveCount() + ",核心线程数:" + pool.getCorePoolSize() + ",线程池大小:" + pool.getPoolSize() + ",队列的大小" + pool.getQueue().size());
pool.shutdown();
//运行结果
//活跃的线程数:1,核心线程数:1,线程池大小:1,队列的大小0
//活跃的线程数:1,核心线程数:1,线程池大小:1,队列的大小1
//活跃的线程数:1,核心线程数:1,线程池大小:1,队列的大小2
//活跃的线程数:2,核心线程数:1,线程池大小:2,队列的大小2
//警告:任务5 被拒绝执行
//活跃的线程数:2,核心线程数:1,线程池大小:2,队列的大小2
//id:1,name:任务1
//警告:任务6 被拒绝执行
//活跃的线程数:2,核心线程数:1,线程池大小:2,队列的大小2
//id:4,name:任务4
//id:3,name:任务3
//id:2,name:任务2
}
}