多线程之阻塞队列ArrayBlockingQueue,BlockingQueue

ArrayBlockingQueue是个有数组支持的有界的阻塞队列。该队列按照先进先出FIFO的原理对元素排序,插入新元素市场队列的尾部,获取新元素是操作队列的开始处。一旦见了建立了缓存区,就不能再增加其容量,试图从已满的队列中方式元素会导致操作阻塞;试图从空的队列中提取元素将导致阻塞。

多线程之阻塞队列ArrayBlockingQueue,BlockingQueue_第1张图片

提拱了四种方法,只有put(),take()才会发生阻塞。

下面是阻塞队列的例子。

package andy.thread.test;

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

/**
 * @author Zhang,Tianyou
 * @version 2014年11月9日 下午5:29:28
 */

public class BlockingQueueTest {

	public static void main(String[] args) {
		final int CAPACITY = 3;
		BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(CAPACITY);
		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,观察运行结果
						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();

	}

}


定义3各大小的阻塞队列,定义了两个线程,一个取,一个存。执行结果如下:

Thread-0准备放数据!
Thread-0已经放了数据,队列目前有1个数据
Thread-1准备放数据!
Thread-1已经放了数据,队列目前有2个数据
Thread-0准备放数据!
Thread-0已经放了数据,队列目前有3个数据
Thread-1准备放数据!
Thread-0准备放数据!
Thread-2准备取数据!
Thread-2已经取走数据,队列目前有2个数据
Thread-1已经放了数据,队列目前有3个数据


2、 可以使用阻塞队列完成两个线程循环交替打印。

我们需要定义两个大小唯一的阻塞队列,当一个线程执行时,给另一个队列里存一个值,让另一个线程处于阻塞状态;当前线程执行完毕时,将另一个阻塞队列取出值,让对应的线程执行。

实例如下:

package andy.thread.test;

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

/**
 * @author Zhang,Tianyou
 * @version 2014年11月9日 下午5:43:28
 */

public class BlockingQueueCommunication {

	public static void main(String[] args) {
		A a = new A();
		new Thread(new Runnable() {

			@Override
			public void run() {
				for (int i = 1; i <= 3; i++) {
					a.sub(i);
				}

			}
		}).start();

		for (int i = 1; i <= 3; i++) {
			a.main(i);
		}

	}

	static class A {
		BlockingQueue<Integer> mainQueue = new ArrayBlockingQueue<Integer>(1);
		BlockingQueue<Integer> subQueue = new ArrayBlockingQueue<Integer>(1);

		// 定义一个匿名构造函数 匿名构造函数在所有的构造函数前开始执行 new多少个实例执行多少次
		// static 是在JVM加载时执行 执行一次
		{
			try {
				subQueue.put(1);// 阻塞子线程 先让第主线程执行
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		public void sub(int i) {
			try {
				// 阻塞主线程
				subQueue.put(1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			System.out.println("sub thread task is " + i);

			try {
				mainQueue.take(); // 子线程执行完 让改主线程执行
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

		public void main(int i) {
			try {
				// 阻塞主线程
				mainQueue.put(1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			System.out.println("main thread task is " + i);

			try {
				subQueue.take(); // 子线程执行完 让改主线程执行
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

	}

}

运行效果如下

main thread task is 1
sub thread task is 1
main thread task is 2
sub thread task is 2
main thread task is 3
sub thread task is 3

你可能感兴趣的:(多线程,并发,BlockingQueue,阻塞队列)