通过上一篇对CountDownLatch的使用,我们也明白了他的基本原理,接下来我们一起来实现一个CountDownLatch的基础效果
新建一个抽象类,包含countDownLatch需要的参数和方法
package com.atguigu.signcenter.nosafe.chouxiang;
/**
* @author: jd
* @create: 2024-09-03
*/
public abstract class Latch {
// 控制了多少线程完成后门阀才能打开
protected int limit;
//构造函数
public Latch(int limit){
this.limit =limit;
}
// 方法使得线程一直等待
public abstract void await() throws InterruptedException;
//当前任务线程完成工作之后调用该方法使得计数器减一
public abstract void countDe();
// 获取当前还有多少个线程没有完成任务
public abstract int getUnArrived();
}
现这个抽象类,并写入具体逻辑代码
package com.atguigu.signcenter.nosafe.chouxiang.chouxiangImpl;
import com.atguigu.signcenter.nosafe.chouxiang.Latch;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author: jd
* @create: 2024-09-03
*/
public class LatchImpl extends Latch {
//创建锁对象
private final Lock lock = new ReentrantLock();
//创建条件对象,但是作用待深入研究
private final Condition condition = lock.newCondition();
//LatchImpl的构造方法,用于计数器的初始化
public LatchImpl(int limit){
super(limit);
}
/**
* 重写等待方法
* @throws InterruptedException
*/
@Override
public void await() throws InterruptedException {
lock.lock();
while (limit > 0){
//如果进入到这里面之后,在await之后,会直接释放掉锁,不走后面的unlock()了;
condition.await();
}
lock.unlock();
}
/**
* 重写计数器减一方法
*/
@Override
public void countDe() {
lock.lock();
while (limit<0){
throw new IllegalStateException();
}
limit--;
//对 condition.await(); 的线程进行唤醒,让他继续执行。
condition.signalAll();
lock.unlock();
}
/**
* 重写获取 当前未完成线程方法
* @return
*/
@Override
public int getUnArrived() {
return limit;
}
}
测试
package com.atguigu.signcenter.nosafe;
import com.atguigu.signcenter.nosafe.chouxiang.chouxiangImpl.LatchImpl;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author: jd
* @create: 2024-09-03
*/
public class LatchTest {
// 创建一个线程池来执行任务
static final ThreadPoolExecutor executor = new ThreadPoolExecutor(6,10,30L,
TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(), Executors.defaultThreadFactory());
public static void main(String[] args) throws InterruptedException {
LatchImpl latch = new LatchImpl(2);
//模拟小红
executor.submit(new Runnable() {
@Override
public void run() {
System.out.println("小红出发了");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDe();
System.out.println("小红到了");
}
});
//模拟小明
executor.submit(() -> {
System.out.println("小明出发了");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDe();
System.out.println("小明到了");
});
latch.await();
System.out.println("都到了,一起去爬山了");
executor.shutdown();
}
}
测试结果: