引自 https://segmentfault.com/a/1190000011207824
SynchronousQueue 是 blocking queue 队列的一种,它的作用是,当一个线程执行插入操作(put)的时候,必须等待另一个线程执行对应的删除操作(take),反之,一个线程如果要执行删除操作则必须等待另一个线程执行插入操作。
1.SynchronousQueue内部实现中并没有容量的概念,所以不能执行 peek 操作,因为只有在线程试图执行remove操作的时候才有一个元素存在。
//SynchronousQueue
public E peek() {
return null;
}
2.不能成功插入一个元素(add, off, put方法)除非另一个线程试图执行删除操作。
public void test01() throws InterruptedException {
final BlockingQueue<LocalDateTime> synchronousQueue = new SynchronousQueue();
new Thread(()->{
LocalDateTime localDateTime = LocalDateTime.now();
try {
synchronousQueue.put(localDateTime); //put 操作`尚未`完成,会阻塞等待另外线程的take
System.out.println("put:"+ localDateTime);
} catch (InterruptedException e) {
}
}).start();
// synchronousQueue.take(); // 注释掉此行代码后,程序会阻塞
}
3.也不能迭代队列,因为其中没有元素可用于迭代。
public Iterator<E> iterator() {
return Collections.emptyIterator();
}
例
public class SynchronousQueueExample {
public static void main(String[] args) {
BlockingQueue<Integer> synchronousQueue = new SynchronousQueue();
final AtomicInteger taskNoAtomic = new AtomicInteger(0);
Runnable producerTask = () -> {
while (true) {
try {
int taskNo = taskNoAtomic.getAndIncrement();
synchronousQueue.put(taskNo); //阻塞等待另外一个线程的 take()
System.out.println("Put: " + taskNo);
} catch (InterruptedException e) {
}
}
};
new Thread(producerTask,"producer_1").start();
Runnable consumerTask = () -> {
while (true) {
try {
int taskNo = synchronousQueue.take();
//模拟消费业务逻辑-sleep
TimeUnit.MILLISECONDS.sleep(ThreadLocalRandom.current().nextInt(100));
System.out.println("take(): " + taskNo+"---------------by[" + Thread.currentThread().getName()+"]");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
new Thread(consumerTask,"consumer_1").start();
new Thread(consumerTask,"consumer_2").start();
}
}
Executors.newCachedThreadPool()
demo
public class SynchronousQueueExample2 {
public static void main(String[] args) {
// prt(Executors.newSingleThreadExecutor());
// prt(Executors.newFixedThreadPool(3));
prt(Executors.newCachedThreadPool());
}
public static void prt(ExecutorService service) {
AtomicInteger integer = new AtomicInteger();
for(int i = 0 ; i < 10 ; i++){
service.submit(() -> {
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"))+"---"+integer.getAndIncrement());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
}
Executors.newCachedThreadPool()
再看一下Executors.newCachedThreadPool()
部分代码:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
ThreadPoolExecutor—源码分析
先回顾下ThreadPoolExecutor
// ThreadPoolExecutor
/**
* @param corePoolSize 核心线程数
* @param maximumPoolSize 线程池最大线程数(核心线程+工作线程)
* @param keepAliveTime 线程池线程数 > 核心线程数时,工作线程最大空闲时间
* @param unit 空闲时间单位
* @param workQueue 用来持有未被线程执行的Runnable-task;
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
ThreadPoolExecutor 执行任务(Runnable-task
)的过程:
- 当
线程池线程数<核心线程数时,创建核心线程
– 成功 return;否则跳转至2 - 尝试向任务队列(workQueue)里添加任务 – 失败
(队列满)
,跳转至3 - 尝试新增worker线程;
Executors.newCachedThreadPool()
使用SynchronousQueue
,表示执行到2
时,每次向队列中添加任务都会失败,都会跳转到3