个人主页:五敷有你
系列专栏:并发编程
⛺️稳重求进,晒太阳
示意图
变量定义
方法:
public class MyBlockQueue {
//1.任务队列
private Deque deque=new ArrayDeque();
//2.锁
private ReentrantLock lock=new ReentrantLock();
//3.生产者条件变量
private Condition fullWaitSet=lock.newCondition();
//4.消费者条件变量
private Condition emptyWaitSet=lock.newCondition();
//5.容量
private int capcity;
public MyBlockQueue(int capcity) {
this.capcity = capcity;
}
//带超时的阻塞获取
public T poll(long timeOut, TimeUnit unit){
lock.lock();
try {
//将timeOUt转换成统一转换为ns
long nanos = unit.toNanos(timeOut);
while (deque.isEmpty()) {
try {
//返回值=等待时间-经过的时间
if(nanos<=0){
return null;
}
nanos= emptyWaitSet.awaitNanos(nanos);
}catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
T t = deque.removeFirst();
fullWaitSet.signalAll();
return t;
}finally {
lock.unlock();
}
}
//6. 阻塞获取
public T take() {
lock.lock();
try {
while (deque.isEmpty()) {
try {
emptyWaitSet.await();
}catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
T t = deque.removeFirst();
fullWaitSet.signalAll();
return t;
}finally {
lock.unlock();
}
}
//阻塞添加
public void put(T element){
lock.lock();
try {
while (deque.size()==capcity){
try {
fullWaitSet.await();
}catch (Exception e){
}
}
deque.addLast(element);
emptyWaitSet.signalAll();
} finally {
lock.unlock();
}
}
public int size(){
lock.lock();
try {
return deque.size();
}finally {
lock.unlock();
}
}
}
package com.aqiuo.juc;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;
public class ThreadPool {
//任务队列
private MyBlockQueue taskQueue;
//队列容量
int queueCapcity;
//线程集合
private HashSet workers=new HashSet();
//线程池的核心线程
private int coreSize;
//获取任务的超时时间
private long timeOut;
//时间单位
private TimeUnit timeUnit;
public ThreadPool(int coreSize, long timeOut, TimeUnit timeUnit,int queueCapcity) {
this.coreSize = coreSize;
this.timeOut = timeOut;
this.timeUnit = timeUnit;
taskQueue=new MyBlockQueue<>(queueCapcity);
}
public void exectue(Runnable task){
//当任务数没有超过coreSize时,直接交给work对象执行
//如果任务超过coreSize时,加入任务队列
synchronized (workers){
if(workers.size()
测试
开启15个线程测试
public static void main(String[] args) {
ThreadPool threadPool = new ThreadPool(2, 1000, TimeUnit.MILLISECONDS, 10);
for (int i=0;i<15;i++){
int j=i;
threadPool.exectue(()->{
System.out.println(j);
});
}
}
执行过程中,超过了队列容量之后,就会发生fullWaitSet阻塞。这个阻塞的线程就开始等待,当有队列不满之后,唤醒fullWaitSet阻塞的队列,
同理,当队列为空,emptyWaitSet小黑屋阻塞,当有任务被放入,EmptyWaitSet唤醒所有的线程。
这就有一个执行完毕之后,线程不会停止,他会一定等待拿去任务,线程阻塞了EmptyWaitSet
获取任务take的增强 超时
//带超时的阻塞获取
public T poll(long timeOut, TimeUnit unit){
lock.lock();
try {
//将timeOUt转换成统一转换为ns
long nanos = unit.toNanos(timeOut);
while (deque.isEmpty()) {
try {
//返回值=等待时间-经过的时间
if(nanos<=0){
return null;
}
nanos= emptyWaitSet.awaitNanos(nanos);
}catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
T t = deque.removeFirst();
fullWaitSet.signalAll();
return t;
}finally {
lock.unlock();
}
}
修改worker的run函数
public void run() {
//执行任务
//1)当task不为空,执行任务
//2)当task执行完毕,再接着从任务队列中获取任务
// while (task!=null||(task=taskQueue.take())!=null){
//修改如下
while (task!=null||(task=taskQueue.poll(timeOut,timeUnit))!=null){
try {
System.out.println("正在执行worker"+this);
sleep(1000);
task.run();
} catch (Exception e) {
}finally {
task=null;
}
}
正常结束了
那么有装入任务 的增强 ,就再提供一个超时装入入offer()吧 ,当放入一个满的队列时,超时后返回false不再放入
//带有超时的队列添加
public Boolean offer(T element,long timeOut, TimeUnit unit){
lock.lock();
long nanos = unit.toNanos(timeOut);
try {
while (deque.size()==capcity){
try {
long l = fullWaitSet.awaitNanos(nanos);
if(l<=0){
return false;
}
}catch (Exception e){
}
}
deque.addLast(element);
emptyWaitSet.signalAll();
return true;
} finally {
lock.unlock();
}
}
@FunctionalInterface // 拒绝策略
interface RejectPolicy {
void reject(MyBlockQueue queue, T task);
}
如下部分代码是存入任务的部分
public void exectue(Runnable task){
//当任务数没有超过coreSize时,直接交给work对象执行
//如果任务超过coreSize时,加入任务队列
synchronized (workers){
if(workers.size()
阻塞队列里的tryPut
public void tryPut(ThreadPool.RejectPolicy rejectPolicy, T task) {
lock.lock();
try {
//如果队列容量满了,就开始执行拒绝策略
if(capcity>= deque.size()){
rejectPolicy.reject(this,task);
}else{
//不满就正常加入到队列中
System.out.println(task+"正常加入到队列");
deque.addLast(task);
}
}finally {
lock.unlock();
}
}
//1) 死等
//2)带有超时的等待
//3)当调用者放弃任务执行
//4)让调用者抛出异常
//5)让调用者自己执行任务...
谁调用方法,谁写拒绝策略
为了传入策略,就再构造函数里面加入一个方法的参数传入
//部分代码...
//拒绝策略
RejectPolicy rejectPolicy;
public ThreadPool(int coreSize, long timeOut, TimeUnit timeUnit,int queueCapcity,RejectPolicy rejectPolicy) {
this.coreSize = coreSize;
this.timeOut = timeOut;
this.timeUnit = timeUnit;
taskQueue=new MyBlockQueue<>(queueCapcity);
this.rejectPolicy=rejectPolicy;
}
主函数编写拒绝的策略,就lamda表达式会把...
public static void main(String[] args) {
ThreadPool threadPool = new ThreadPool(1, 1000, TimeUnit.MILLISECONDS, 1,(queue,task)->{
//死等
// queue.put(task);
//超时添加
// System.out.println(queue.offer(task, 100, TimeUnit.NANOSECONDS));
//放弃执行
// System.out.print("我放弃");
//调用者抛出异常
// throw new RuntimeException("任务执行失败");
//调用者执行
// task.run();
});
for (int i=0;i<5;i++){
int j=i;
threadPool.exectue(()->{
System.out.println(j);
});
}
}
1.死等的结果
2.超时拒绝的结果(每个false都是时间到了,每加进去)
3.不作为,调用者放弃任务
4.抛出异常,停止
5.调用者线程执行了