用java自己实现代码阻塞的几种方式
假如有一个场景,当代码获取的变量不为期待值的时候需要等待变量变为期待值再往下执行,最开始可能会考虑通过死循环+线程睡眠来实现,但是这样子毕竟不太合理。可以通过以下方式来实现:
- 通过阻塞队列。
import java.util.concurrent.*;
/**
1. 自己用阻塞队列实现代码的阻塞
*/
public class BlockCode {
//创建一个线程池
private static ThreadPoolExecutor executor = new ThreadPoolExecutor(5,10,1, TimeUnit.MINUTES,new LinkedBlockingQueue<>(100));
//创建一个容量为1的阻塞队列
private static BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<>(1);
public static void main(String[] args) {
//吃包子
executor.execute(()->{
try {
//队列空时获取会阻塞
Integer num = blockingQueue.take();
System.out.println("成功吃上包子");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
executor.execute(()->{
try {
Thread.sleep(3000);
System.out.println("上架一个包子");
//队列满了插入会阻塞
blockingQueue.put(0);
} catch (Exception e) {
e.printStackTrace();
}
});
}
}
- 通过等待唤醒,wait和notify
/**
* 通过等待唤醒实现阻塞
*/
public class BlockCode2 {
private static ThreadPoolExecutor executor = new ThreadPoolExecutor(5,10,1, TimeUnit.MINUTES,new LinkedBlockingQueue<>(100));
public static void main(String[] args) {
executor.execute(()->{
//假如从数据库查询出来一个包子,这里不考虑线程安全
String bread = null;
if (bread==null){
synchronized ("包子"){
try {
"包子".wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("成功吃上包子");
}
});
executor.execute(()->{
try {
//做包子时间
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//假如生产了一个包子并且放入了数据库了
System.out.println("上架一个包子");
synchronized ("包子"){
//唤醒所有等待的线程
"包子".notifyAll();
}
});
}
}