JDK5新特性之阻塞队列(四)

一. 阻塞队列和普通队列:

队列是一种基本的数据类型,其典型特征是先进先出。

阻塞队列和普通队列的区别在于:

当队列为空时,从队列中获取元素的线程会被阻塞,直到其他的线程往空的队列里插入新的元素;

当队列是满的时,往队列里添加元素的操作会被阻塞,直到其他的线程从队列移除一个或多个元素;

上图中:线程1往阻塞队列里添加元素,而线程2从阻塞队列里移除元素

/**
 * 阻塞队列的简单实现
 */
public class BlockingQueue<T> {

	private List<T> queue = new LinkedList<T>();

	private int limit = 10;

	public BlockingQueue(){
	}

	public BlockingQueue(int limit) {
		this.limit = limit;
	}

	// 入队
	public synchronized void enqueue(T obj) throws InterruptedException {
		while (this.queue.size() == this.limit) {
			wait();
		}
		if (this.queue.size() == 0) {
			notifyAll();
		}
		this.queue.add(obj);
	}

	// 出队
	public synchronized Object dequeue() throws InterruptedException {
		while (this.queue.size() == 0) {
			wait();
		}
		if (this.queue.size() == this.limit) {
			notifyAll();
		}
		return this.queue.remove(0);
	}
}

二. API实现:

BlockingQueue是一个接口,有以下实现类:

1. ArrayBlockQueue:一个由数组支持的有界阻塞队列,此队列遵循先进先出原则排序,创建其对象必须明确大小。

2. LinkedBlockQueue:一个可改变大小的阻塞队列,此队列遵循先进先出原则排序,创建其对象没有明确大小,并发程序中,性能稍差。

3. PriorityBlockingQueue: 类似LinkedBlockQueue,但其所含对象的排序不是先进先出,而是依据对象的自然排序顺序或构造函数所带的Comparator决定

4. SynchronousQueue:同步队列, 每插入一个必须等待另一个线程移除。

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

public class BlockingQueueTest {

	public static void main(String[] args) {

		// 阻塞队列类: 队列中可以存3个数据
		final BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(3);

		// 开启3个线程不断的存数据
		for (int i = 0; i < 3; 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() + " 个数据!");
							Thread.sleep(1000);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
			}.start();
		}

		// 开启一个线程不断的取数据
		new Thread() {
			public void run() {
				while (true) {
					try {
						Thread.sleep(1000);
						System.out.println(Thread.currentThread().getName() + " 准备取数据!");
						queue.take(); // 从队列中取数据
						System.out.println(Thread.currentThread().getName()
								+ " 已经取走数据,队列目前有: " + queue.size() + " 个数据!");
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}.start();
	}
}
Thread-1 准备放数据!
Thread-1 已经放了数据,队列目前有: 1 个数据!
Thread-0 准备放数据!
Thread-0 已经放了数据,队列目前有: 2 个数据!
Thread-2 准备放数据!
Thread-2 已经放了数据,队列目前有: 3 个数据!
Thread-3 准备取数据!
Thread-3 已经取走数据,队列目前有: 2 个数据!
Thread-1 准备放数据!
Thread-1 已经放了数据,队列目前有: 3 个数据!
Thread-0 准备放数据!
Thread-2 准备放数据!
Thread-3 准备取数据!
Thread-3 已经取走数据,队列目前有: 2 个数据!
Thread-0 已经放了数据,队列目前有: 3 个数据!
Thread-1 准备放数据!
Thread-0 准备放数据!
Thread-3 准备取数据!
Thread-3 已经取走数据,队列目前有: 2 个数据!
Thread-2 已经放了数据,队列目前有: 3 个数据!

时间: 2024-11-04 21:35:26

JDK5新特性之阻塞队列(四)的相关文章

Java API —— JDK5新特性

JDK5新特性 自动拆装箱.泛型.增强for.静态导入.可变参数.枚举   1.增强for概述 1)简化数组和Collection集合的遍历 2)格式: for(元素数据类型 变量 : 数组或者Collection集合) { 使用变量即可,该变量就是元素 } 3)好处:简化遍历 4)注意事项:增强for的目标要判断是否为null 例子1: package jdk5; import java.util.ArrayList; import java.util.List; /** * Created

JDK5新特性之 可变参数的方法

可变参数的方法:不知道这个方法该定义多少个参数 注意: > 参数实际上是数组 > 必须写在参数列表最后一个 package cn.itcast.day24.varparam; import java.lang.reflect.Type; /** * * JDK5新特性之 可变参数 * 定义方法时,不知道该定义多少个参数 * * 格式: * 修饰符 方法返回值 方法名(数据类型 ... 变量名){} * * 注意: * 可变参数实际上是一个数组 * 可变参数必须写在方法的参数列表的最后 * */

java 基础加强(myeclipse,debug,junit,JDK5新特性,反射)

思维导图 1.myeclipse的安装和使用 *eclipse:是一个免费的开发工具 *myeclipse:是一个收费的插件,破解myeclipse, **安装目录的要求: 不能有中文和空格 **安装完成之后,选择一个工作空间 ,这个工作空间不能有中文和空格 *破解myeclipse **运行run.bat文件,但是运行之前,必须要安装jdk,通过配置环境变量 *myeclipse的使用 *创建一个工程 -类型 javaproject  web  project -选择依赖的jdk,可以使用my

泛型,JDK5新特性,List集合子实现类,Map集合,Set/TreeSet集合,asList

一.泛型(JDK5以后新特性) 1.概述:泛型直接规定集合的存储类型,将明确的集合类型的工作推迟到了创建对象或者调用方法的时候,属于一种参数化类型,可作参数传递.2.优点(1)将运行时期异常提前到了编译时期:(2)优化了设计,解决了×××警告线问题:(3)避免了强制类型转换, ,解决了向下类型转换出现的问题ClassCastException:(4)泛型的引出可以提供程序的安全性.3.泛型定义在类上(1)格式:public class 类名<T>{--}(2)实例:实体类: 测试类: 4.泛型

Goldengate 12.2新特性-自描述的队列文件

OGG12.2中最大的变化之一就是队列文件是自描述的,意思是不再担心以前版本中,表结构异构的情况,也不再需要defgen生成定义文件,以及不再使用assumeTargetDefs或SourceDefs参数.许多手工处理的步骤不再需要了.即使源和目标是不同的平台或数据库也是如此.因为队列文件中已经包含了表结构等元信息. 下面的示例中会演示这个特性,现在队列文件中包含有两个重要的信息DDR(数据库定义记录)和TDR(表定义记录).每个队列文件在某个库的任何一个DML或序列操作之前都会包含一个DDR,

JDK5新特性之泛型

泛型是一种把类型明确的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型. 泛型的格式: <数据类型> 注意:此处的数据类型这能是引用类型 好处: A:把运行时期的问题提前到了编译期间 B:避免了强制类型转换 C:优化了程序设计 import java.util.ArrayList;public class ArrayListDemo { public static void main(String[] args) { ArrayList array = new ArrayList();

JDK5新特性--可变参数

1.可变参数的引入 package cn; /**  * 可变参数  */ public class ChangeParameterDemo { public static void main(String[] args) { //2个数求和 int a = 10; int b = 20; int result = sum(a,b); System.out.println("result:"+result); int c = 30; result = sum(a,b,c); Syste

JDK5新特性之线程同步集合(五)

一. 传统集合: 传统方式下的Collection在迭代集合时, 不同意对集合进行改动: public class CollectionModifyExceptionTest { public static void main(String[] args) { Collection<String> list = new ArrayList<String>(); list.add("aaa"); list.add("bbb"); list.ad

JDK5新特性之同步集合(五)

一. 传统集合: 传统方式下的Collection在迭代集合时, 不允许对集合进行修改: public class CollectionModifyExceptionTest { public static void main(String[] args) { Collection<String> list = new ArrayList<String>(); list.add("aaa"); list.add("bbb"); list.ad