线程池的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后线程创建后启动这些任务,如果线程数量超过了最大数量,超出的线程排队等候,等待其他完成后再从队列取出执行
主要特点:
- 线程复用
- 控制最大并发数
- 管理线程
- 降低资源消耗,通过重复利用已有已经创建好的线程来降低线程创建和销毁造成的消耗
- 提高响应速度,当任务到达时,任务可以不需要等到线程创建就能立即执行
- 提高线程的可管理性,线程是稀缺资源,如果无限制创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控
组件:
- 阻塞队列
- 线程池 work
- 拒绝策略
- main
package com.qyc.pattern.pool;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author qyc
* @time 2020/6/6 - 0:51
*/
public class MyPool{
public static void main(String[] args) {
ThreadPoll threadPoll = new ThreadPoll(4,1000,TimeUnit.MILLISECONDS,
2, (queue,task)->{ queue.offer(task,1,TimeUnit.SECONDS); });
//死等 queue.put(task)
//超时等待 offer task 1500 TimeUtil.MILLISECONDS
//拒绝策略 task.run();
for (int i = 0; i < 10; i++) {
int j = i;
threadPoll.execute(()->{
try{
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("j: "+j);
});
}
}
}
//拒绝策略
@FunctionalInterface
interface RejectPolicy<T>{
void reject(BlockingQueue<T> queue,T task);
}
class BlockingQueue<T>{
//任务队列
private Deque<T> queue = new ArrayDeque<>();
private ReentrantLock lock = new ReentrantLock();
private Condition full = lock.newCondition();
private Condition empty = lock.newCondition();
//容量
private int capcity;
public BlockingQueue(int capcity) {
this.capcity = capcity;
}
//阻塞获取
public T task(){
lock.lock();
try {
//判断
while (queue.isEmpty()){
try{
empty.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//干活
T t = queue.removeFirst();
//通知
full.signal();
return t;
}finally {
lock.unlock();
}
}
//带超时的阻塞获取
public T poll(long timeout,TimeUnit unit){
lock.lock();
try{
long nanos = unit.toNanos(timeout);
while (queue.isEmpty()){
if(nanos<=0){
return null;
}
try {
nanos = empty.awaitNanos(nanos);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
T t = queue.removeFirst();
full.signal();
return t;
} finally {
lock.unlock();
}
}
//阻塞添加
public void put(T task){
lock.lock();
try{
while (queue.size() == capcity){
System.out.println("等待加入任务队列");
full.await();
}
queue.addLast(task);
empty.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//带超时阻塞添加
public boolean offer(T task,long timeout,TimeUnit timeUnit){
lock.lock();
try {
long nanos = timeUnit.toNanos(timeout);
while (queue.size()==capcity){
try {
if(nanos<=0){
return false;
}
nanos = full.awaitNanos(nanos);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.addLast(task);
System.out.println("offer添加");
empty.signal();
return true;
}finally {
lock.unlock();
}
}
//求size
public int size(){
lock.lock();
try{
return queue.size();
}finally {
lock.unlock();
}
}
//带拒绝策略添加
public void tryPut(RejectPolicy<T> rejectPolicy,T task){
lock.lock();
try {
if (queue.size() == capcity){
rejectPolicy.reject(this,task);
}else {
queue.addLast(task);
empty.signal();
}
}finally {
lock.unlock();
}
}
}
class ThreadPoll{
//任务队列
private BlockingQueue<Runnable> taskQueue;
//线程集合
private HashSet<Worker> workers = new HashSet<>();
//核心线程数
private int coreSize;
//超时时间
private long timeout;
private TimeUnit timeUnit;
//拒绝策略
private RejectPolicy<Runnable> rejectPolicy;
public ThreadPoll(int coreSize, long timeout, TimeUnit timeUnit,
int queueCapcity,RejectPolicy<Runnable> rejectPolicy) {
this.coreSize = coreSize;
this.timeout = timeout;
this.timeUnit = timeUnit;
this.rejectPolicy = rejectPolicy;
this.taskQueue = new BlockingQueue<>(queueCapcity);
}
//执行
public void execute(Runnable task){
//当任务没有超过coreSize时,直接交给worker对象执行
//如果任务数超过,加入任务队列保存
synchronized (workers){
if(workers.size()<coreSize){
Worker worker = new Worker(task);
workers.add(worker);
worker.start();
}else {
//死等
//带超时时间
//让调用者放弃任务
//让调用者抛出异常
//让调用者自己执行
// taskQueue.tryPut(rejectPolicy,task);
System.out.println("开始存入");
taskQueue.offer(task,2,TimeUnit.SECONDS);
}
}
}
class Worker extends Thread {
private Runnable task;
public Worker(Runnable task) {
this.task = task;
}
@Override
public void run() {
//执行 当task不为空,执行,当task执行完毕,接着从任务队列获取任务并执行
while (task != null || (task = taskQueue.poll(timeout, timeUnit)) != null) {
try {
task.run();
} finally {
task = null;
}
}
}
}
}
开始存入
offer添加
开始存入
offer添加
开始存入
j: 0
offer添加
开始存入
j: 2
j: 1
offer添加
开始存入
j: 3
offer添加
开始存入
offer添加
j: 4
j: 5
j: 7
j: 6
j: 8
j: 9
JUC线程池
参数
ThreadPoolExecutor(int corePoolSize, //常驻核心线程数
int maximumPoolSize, //线程池能够容纳同时执行的最大线程数
long keepAliveTime, //多余空闲线程存活时间,当空间达到keepAliveTime时多余线程会被销毁直到只剩下corePoolSize个线程为止
TimeUnit unit,
BlockingQueue<Runnable> workQueue, //任务队列
ThreadFactory threadFactory, //生成线程的线程工厂
RejectedExecutionHandler handler) //拒绝策略
// AbortPolicy(默认):直接抛出RejectedExecutionException异常阻止 系统正常运行
// CallerRunsPolicy:“调用者运行”一-种调节机制,该策略既不会抛弃任务,也不
// 会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量。
// DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加人队列中
// 尝试再次提交当前任务。
// DiscardPolicy:该策略默默地丢弃无法处理的任务,不予任何处理也不抛出异常。
// 如果允许任务丢失,这是最好的一种策略。
ExecutorService executors = new ThreadPoolExecutor(2,4,1L, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(),Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
自定义:
- CPU密集型 :需要大量的运算,而没有阻塞,CPU一直全速运行 公式:CPU核数+1个线程的线程池
- IO密集型:任务线程并不是一直在执行任务,则应配置尽可能多的线程,如CPU核数*2
- 任务需要大量IO,大量的阻塞,CPU核数/1-阻塞系数 一般在0.8-0.9 8核CPU 8/1-0.9 = 80个线程
Runtime.getRuntime().availableProcessors() = 4
newFixedThreadPool
固定大小线程池
public class FixedDemo {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(4);
pool.submit(()->{
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(1);
});
pool.submit(()->{
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(2);
});
pool.shutdown();
}
}
newCachedThreadPool
缓存线程池
newSingleThreadExecutor
单例线程池