`

JDK1.5 Queue

阅读更多

JDK1.5 Queue

LinkedList

LinkedList不是同步的。如果多个线程同时访问列表,而其中至少一个线程从结构上修改了该列表,则它必须 保持外部同步。(结构修改指添加或删除一个或多个元素的任何操作;仅设置元素的值不是结构修改。)这一般通过对自然封装该列表的对象进行同步操作来完成。如果不存在这样的对象,则应该使用 Collections.synchronizedList 方法来包装该列表。最好在创建时完成这一操作,以防止对列表进行意外的不同步访问,如下所示:

List list = Collections.synchronizedList(new LinkedList(...));

将指定元素追加到列表的结尾有addoffer两个方法,区别是offer是接口 Queue<E>中的,add是接口 Collection<E> 中的。offer使用可能有插入限制(例如容量限定)的队列时,offer方法通常要优于 Collection.add(E) 方法,因为add只能通过抛出异常使插入元素失败。而offer方法的返回值是:如果可以向此队列添加元素,则返回 true;否则返回 false

找到并移除列表的头(第一个元素)有pollremove两个方法,区别是poll是接口 Queue<E>中的,remove是接口 Queue<E>中的。如果队列为空,poll返回null,而remove抛出NoSuchElementException

找到但不移除列表的头(第一个元素)是peek方法

 

实例:

package com.bijian.thread;

import java.util.LinkedList;
import java.util.Queue;

public class UseLinkedList {

	public static void main(String[] args) {
		Queue<String> queue = new LinkedList<String>();
		queue.offer("Hello");
		queue.offer("World!");
		queue.offer("你好!");
		System.out.println(queue.size());
		String str;
		while ((str = queue.poll()) != null) {
			System.out.println(str);
		}
		System.out.println();
		System.out.println(queue.size());
	}
}

 

运行结果:
3
Hello
World!
你好!

0

 

ArrayBlockingQueue

       一个由数组支持的有界阻塞队列。此队列按 FIFO(先进先出)原则对元素进行排序。队列的头部 是在队列中存在时间最长的元素。队列的尾部 是在队列中存在时间最短的元素。新元素插入到队列的尾部,队列检索操作则是从队列头部开始获得元素。

ArrayBlockingQueue的常用方法:

       put:将指定的元素添加到此队列的尾部,如果必要,将等待可用的空间。

       take:检索并移除此队列的头部,如果此队列不存在任何元素,则一直等待。

       offer:将指定的元素插入到此队列的尾部(如果可能),如果此队列已满,则立即返回。

       poll:检索并移除此队列的头,如果此队列为空,则返回null

说明:putoffer都是向队列中添加元素,takepoll都是从队列中移除元素。puttake对应一组,是阻塞式的;offerpoll对应一组,是非阻塞式的。

 

实例:

 

package com.bijian.thread.blockqueue;

import java.util.concurrent.BlockingQueue;

public class Producer implements Runnable {

	private final BlockingQueue<Character> queue;

	Producer(BlockingQueue<Character> q) {
		queue = q;
	}

	public void run() {
		try {
			for (int i = 0; i < 10; i++) {
				queue.put(produce());
				System.out.println("生产后:" + queue.peek());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	Character produce() {
		char c = (char) (Math.random() * 26 + 'A');
		System.out.println("生产前:" + c);
		return c;
	}
}

 

package com.bijian.thread.blockqueue;

import java.util.concurrent.BlockingQueue;

public class Consumer implements Runnable {
	
	private String name;
	private final BlockingQueue<Character> queue;
	
	public Consumer(String name, BlockingQueue<Character> q) {
		this.name = name;
		this.queue = q;
	}

	@Override
	public void run() {
		
		try {
			while(true) {
				consume(queue.take());
			}
		} catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public void consume(Character c) {
		System.out.println("[" + name + "]消费: " + c);
	}
}

 

package com.bijian.thread.blockqueue;

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

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		BlockingQueue q = new ArrayBlockingQueue(10);
		
		Producer p = new Producer(q);
		Consumer c1 = new Consumer("tom", q);
		Consumer c2 = new Consumer("jacky", q);
		new Thread(c1).start();
		new Thread(c2).start();
		new Thread(p).start();
	}
}

 运行结果(打印结束后程序一直未结束,但也未输出,处于阻塞状态):

生产前:L
生产后:L
生产前:Q
[tom]消费: L
[jacky]消费: Q
生产后:Q
生产前:G
生产后:G
[tom]消费: G
生产前:O
生产后:O
[jacky]消费: O
生产前:M
生产后:M
[tom]消费: M
生产前:I
生产后:I
[jacky]消费: I
生产前:B
生产后:B
生产前:Q
[tom]消费: B
[jacky]消费: Q
生产后:Q
生产前:D
生产后:D
[tom]消费: D
生产前:A
生产后:A
[jacky]消费: A

 

 

实例2

package com.bijian.thread.blockqueue;

import java.util.concurrent.BlockingQueue;

public class Producer implements Runnable {

	private final BlockingQueue<Character> queue;

	Producer(BlockingQueue<Character> q) {
		queue = q;
	}

	public void run() {
		try {
			for (int i = 0; i < 10; i++) {
				queue.offer(produce());
				//System.out.println("生产后:" + queue.peek());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	Character produce() {
		char c = (char) (Math.random() * 26 + 'A');
		System.out.println("生产前:" + c);
		return c;
	}
}

 

package com.bijian.thread.blockqueue;

import java.util.concurrent.BlockingQueue;

public class Consumer implements Runnable {
	
	private String name;
	private final BlockingQueue<Character> queue;
	
	public Consumer(String name, BlockingQueue<Character> q) {
		this.name = name;
		this.queue = q;
	}

	@Override
	public void run() {
		
		while(true) {
			consume(queue.poll());
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	public void consume(Character c) {
		System.out.println("[" + name + "]消费: " + c);
	}
}

 

package com.bijian.thread.blockqueue;

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

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		BlockingQueue q = new ArrayBlockingQueue(10);
		
		Producer p = new Producer(q);
		Consumer c1 = new Consumer("tom", q);
		Consumer c2 = new Consumer("jacky", q);
		
		new Thread(p).start();
		new Thread(c1).start();
		new Thread(c2).start();
	}
}

  

运行结果(打印结束后程序一直未结束,消费者一直输出null,处于非阻塞状态):

[tom]消费: null
[jacky]消费: null
生产前:S
生产前:R
生产前:N
生产前:S
生产前:P
生产前:U
生产前:J
生产前:Y
生产前:C
生产前:H
[jacky]消费: S
[tom]消费: R
[jacky]消费: N
[tom]消费: S
[tom]消费: P
[jacky]消费: U
[jacky]消费: J
[tom]消费: Y
[jacky]消费: C
[tom]消费: H
[jacky]消费: null
[tom]消费: null
[tom]消费: null
[jacky]消费: null
……

 

 

DelayQueue

       Delayed 元素的一个无界阻塞队列,只有在延迟期满时才能从中提取元素。该队列的头部是延迟期满后保存时间最长的 Delayed 元素。如果延迟都还没有期满,则队列没有头部,并且 poll 将返回 null。当一个元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一个小于或等于零的值时,则出现期满。此队列不允许使用 null 元素。

DelayQueue的常用方法:

       add:将指定元素添加到此队列中。

       offer:将指定元素插入到此延迟队列中。

       put:将指定元素添加到此延迟队列中。由于该队列是无界的,所以此方法永远不会阻塞。

       take:检索并移除此队列的头部,如果此队列不存在未到期延迟的元素,则等待它。

       poll:检索并移除此队列的头部,如果此队列不存在未到期延迟的元素,则返回null

       remove:从此队列中移除指定元素的单个实例(如果存在)。

       drainTo:移除此队列中所有可用的元素,并将它们添加到给定 collection 中。

 

实例:

package com.bijian.thread.blockqueue.delayqueue;

import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class NanoDelay implements Delayed {
	
	private String name;
	private long targetTime;
	
	public NanoDelay(String name, long targetTime) {
		super();
		this.name = name;
		this.targetTime = TimeUnit.NANOSECONDS.convert(targetTime, TimeUnit.NANOSECONDS);
	}

	@Override
	public int compareTo(Delayed o) {
		NanoDelay that = (NanoDelay)o;
		
		return targetTime > that.targetTime?1:(targetTime < that.targetTime?-1:0);
	}

	@Override
	public long getDelay(TimeUnit unit) {
		
		return unit.convert(targetTime, unit.NANOSECONDS);
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("NanoDelay [name=");
		builder.append(name);
		builder.append(", targetTime=");
		builder.append(targetTime);
		builder.append("]");
		return builder.toString();
	}
}

 

package com.bijian.thread.blockqueue.delayqueue;

import java.util.Random;
import java.util.concurrent.DelayQueue;

public class Main {
	
	public static void main(String args[]) {
		
		Random random = new Random();
		DelayQueue<NanoDelay> queue = new DelayQueue<NanoDelay>();
		
		for (int i = 0; i < 5; i++) {
			queue.add(new NanoDelay("T" + i, random.nextInt(5)));
		}
		
		System.out.println("start..");
		System.out.println(queue.size());
		
		for(int i = 0; i < 5; i++) {
			try {
				NanoDelay delay = queue.take();
				System.out.println(delay);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

 

运行结果(打印结束后程序一直未结束,但也未输出,处于阻塞状态):
start..
5
NanoDelay [name=T1, targetTime=0]

  

分享到:
评论

相关推荐

    scjp认证指南JDK1.6,jdk1.5

    11. **泛型**:泛型引入于JDK1.5,用于提高代码的类型安全性和重用性,理解泛型类、泛型方法和通配符的使用。 12. **枚举**:枚举是JDK1.5引入的新特性,用于定义一组固定的值,可以替代传统的常量类。 13. **异常...

    02-JMS熟练应用.pdf

    - 在这种模式下,客户端通过队列(Queue)将消息发送到另一个客户端。 - 发送消息的客户端将消息放入特定的队列中。 - 接收消息的客户端从该队列中提取消息。 - 每个消息只能被一个消费者接收。 2. **发布订阅...

    docs

    ConcurrentQueue ConcurrentStack .NET API 系统 班级 大批 动作 Func 例外 GC 特性最大生成 方法 收集(Int32) CollectionCount(Int32) GetGeneration(对象) GetTotalMemory(布尔) ...

    RocketMQ踩坑

    Name Server是RocketMQ的重要组件之一,主要负责管理主题(Topic)和队列(Queue)的元数据,以及提供Producer和Consumer的路由信息。 在作者的操作过程中,遇到了以下问题: 1. 当试图通过`nohup sh bin/mqnamesrv...

    Java集合

    在JDK1.5以前Java集合会丢失容器中所有对象的数据类型,把所有对象都当初object对象来处理,JDK1.5以后增加了泛型,Java集合可以记住容器中对象的数据类型。从而可以编写出更简洁,健壮的代码。

    Jdk+api+1.6+英文原版 CHM格式

    3. **java.util**:这个包提供了一组实用工具类,包括集合框架(如ArrayList、LinkedList、HashMap)、日期/时间操作(如Date、Calendar)、随机数生成(Random)、队列(Queue)等。集合框架是Java编程中不可或缺的...

    线程-线程池-锁-集合-Map-队列.docx

    此外,`Callable`接口在JDK 1.5后引入,它可以返回一个结果,并且可以抛出异常,相比`Runnable`更具有优势。 线程的状态管理是多线程编程中非常重要的部分。Java线程有六种状态:NEW、RUNNABLE、BLOCKED、WAITING、...

    java 集合源码学习,jdk1.8集合类所有的源码讲解

    在JDK 1.8中,集合框架已经相当成熟和完善,包括List、Set、Queue、Map等接口,以及ArrayList、LinkedList、HashSet、HashMap等实现类。本篇文章将深入探讨这些集合类的源码,揭示其内部实现机制。 首先,我们来看`...

    java performance2

    - **字符串拼接**:在进行字符串拼接时,如果是在循环中拼接字符串,应该使用`StringBuilder`(JDK 1.5及以上版本)或`StringBuffer`(线程安全),而不是使用`+`操作符,因为后者会导致频繁的对象创建和垃圾回收。...

    java基础文档

    7. **JDK 1.5新特性**: - 包括泛型,枚举,自动装箱拆箱,可变参数,增强的for循环(foreach)等,这些极大地提高了代码的可读性和安全性。 8. **多线程**: - Java提供了内置的多线程支持,通过创建Thread对象...

    java大神进阶之路.pdf

    - JDK版本特性:关注JDK1.5、JDK1.6、JDK1.7、JDK1.8等各版本的新特性和提升。 **三、数据库相关** - 理论基础:了解数据库设计原则、范式和事务的基本概念和工作原理。 - 数据库操作:学习MySQL、SQLServer、...

    JMS与Spring之一(用JmsTemplate同步收发消息)

    首先,需要准备好JMS环境,包括JMS 1.1、Apache ActiveMQ 5.4.0、Spring 2.5.4、JDK 1.5和MyEclipse 7.5。 其次,需要创建一个Java项目,包括src/main/java和src/main/resources两个文件夹。在classpath中,需要...

    java学习进阶之路,如果从一个菜鸟进阶成大神(csdn)————程序.pdf

    - **JDK版本更新**:对比JDK1.5至JDK1.8的新特性,如自动装箱拆箱、枚举、泛型、并发工具类等改进。 通过系统学习以上知识点,并结合实际项目经验,你将逐渐积累深厚的技术底蕴,成为一名Java开发领域的专家。记住...

    Java知识笔记.docx

    JDK 1.5后引入了自动装箱和拆箱功能,使得基本类型和包装类之间的转换更为便捷。 5. Collection集合 `Collection`接口是所有单列集合的父接口,它定义了集合的基本操作,如添加、删除和遍历元素。集合与数组的主要...

    JAVA中文API

    这个压缩包文件"JDK1.5API_CN(ȫ).CHM"是Java 1.5版本的中文API帮助文档,通常以CHM(Compiled HTML Help)格式存储,这种格式便于离线查看和搜索。 在Java API中,我们可以找到以下主要知识点: 1. **基础类库**...

    Java集合框架的知识总结.doc

    自JDK 1.5起,Java引入了泛型,使得集合可以限制其存储的元素类型,提高代码的类型安全性和效率。通过在集合声明时指定泛型参数,可以确保插入和取出的元素类型一致。 3. **常用接口与实现类** - `List`接口:最...

    Java程序设计实验报告-计算器.doc

    2. **开发平台**:使用JDK 1.5版本,这是编写和运行Java程序的基础。 四、设计思路 1. **界面构建** - 使用JFrame作为基础窗口,设置大小、关闭行为、是否可调整大小,并添加标题。 - 通过BorderLayout布局管理...

    Java基础学习17.pdf

    增强型for循环(JDK 1.5引入): 增强型for循环,也称为foreach循环,简化了遍历集合的操作。然而,它不支持在迭代过程中修改集合,否则可能会抛出ConcurrentModificationException。 总的来说,熟练掌握Java基础,...

    Java 集合面试稳稳的.pdf

    首先,Collection接口主要有List、Set和Queue三种子接口。List接口用于存储有序且可重复的集合元素,常用的实现类有ArrayList和LinkedList。ArrayList底层是基于动态数组实现的,适合快速随机访问,但插入和删除操作...

Global site tag (gtag.js) - Google Analytics