java多线程之线程并发库阻塞队列的应用

时间:2021-11-04 18:01:57
ArrayBlockingQueue(jdk中已经提供 就在那个condition类说明里的可阻塞示例程序的下面就说明了)
注意三个添加方法的区别->查API文档 拿插入来说 一个会抛异常 一个返回true/false 一个会阻塞
是记不住的 找到doc即可 把精力留出来吧
阻塞队列与Semaphore有些相似,但也不同,阻塞队列是一方存放数据,另一方释放数据,Semaphore通常则是由同一方设置和释放信号量。

用3个空间的队列来演示阻塞队列的功能和效果。 

package javaplay.thread.test;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueTest {
	public static void main(String[] args) {
		final BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(3);
		for (int i = 0; i < 2; i++) {
			new Thread() {
				public void run() {
					while (true) {
						try {
							Thread.sleep((long) (Math.random() * 1000));
							System.out.println(Thread.currentThread().getName() + "准备放数据!");
							queue.put(1);
							System.out.println(Thread.currentThread().getName() + "已经放了数据," + "队列目前有" + queue.size() + "个数据");
						} catch (InterruptedException e) {
							e.printStackTrace();
						}

					}
				}

			}.start();
		}

		new Thread() {
			public void run() {
				while (true) {
					try {
						// 将此处的睡眠时间分别改为100和1000,观察运行结果会发现经常会有3个数据 100则因取得快很少有3
						Thread.sleep(1000);
						System.out.println(Thread.currentThread().getName() + "准备取数据!");
						queue.take();
						System.out.println(Thread.currentThread().getName() + "已经取走数据," + "队列目前有" + queue.size() + "个数据");
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}

		}.start();
	}
}
用两个具有1个空间的队列来实现同步通知的功能。

package javaplay.thread.test;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueCommunication {

	public static void main(String[] args) {

		final Business business = new Business();
		new Thread(new Runnable() {

			@Override
			public void run() {

				for (int i = 1; i <= 5; i++) {
					business.sub(i);
				}

			}
		}).start();

		for (int i = 1; i <= 5; i++) {
			business.main(i);
		}

	}

	static class Business {

		BlockingQueue<Integer> queue1 = new ArrayBlockingQueue<Integer>(1);
		BlockingQueue<Integer> queue2 = new ArrayBlockingQueue<Integer>(1);

		{// 此处不能加static(queue1/queue2都不是static) 这叫匿名构造方法 运行时机在任何构造方法之前
			// Collections.synchronizedMap(null);
			try {
				System.out.println("xxxxxdfsdsafdsa");
				queue2.put(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		public void sub(int i) {
			try {
				queue1.put(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			for (int j = 1; j <= 1; j++) {
				System.out.println("sub thread sequece of " + j + ",loop of " + i);
			}
			try {
				queue2.take();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		public void main(int i) {// 此处不能加synchronized 否则如果main先进去就死锁了
			try {
				queue2.put(1);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			for (int j = 1; j <= 2; j++) {
				System.out.println("main thread sequece of " + j + ",loop of " + i);
			}
			try {
				queue1.take();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}
一个队列可否实现呢?