SynchronousQueue

引自 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)的过程:

  1. 线程池线程数<核心线程数时,创建核心线程 – 成功 return;否则跳转至2
  2. 尝试向任务队列(workQueue)里添加任务 – 失败(队列满),跳转至3
  3. 尝试新增worker线程;

Executors.newCachedThreadPool()使用SynchronousQueue,表示执行到2时,每次向队列中添加任务都会失败,都会跳转到3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值