Java 队列Queue

队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
在队列这种数据结构中,最先插入的元素将是最先被删除的元素;反之最后插入的元素将是最后被删除的元素,因此队列又称为“先进先出”(FIFO—first in first out)的线性表。

     抛出异常 返回特殊值 
插入 add(e)   offer(e) 
移除 remove() poll() 
检查 element() peek() 


Queue使用时要尽量避免Collection的add()和remove()方法,而是要使用offer()来加入元素,使用poll()来获取并移出元素。它们的优点是通过返回值可以判断成功与否,
add()和remove()方法在失败的时候会抛出异常。 如果要使用前端而不移出该元素,使用element()或者peek()方法。
element方法是在队列为空的时候抛异常,而peek则是返回null。

LinkedList类实现了Queue接口

public class QueueTest {
	public static void main(String[] args) {
		// add()和remove()方法在失败的时候会抛出异常(不推荐)
		Queue<String> queue = new LinkedList<String>();
		// 添加元素
		queue.offer("a");
		queue.offer("b");
		queue.offer("c");
		queue.offer("d");
		queue.offer("e");
		for (String q : queue) {
			System.out.println(q);
		}
		System.out.println("===");
		System.out.println("poll=" + queue.poll()); // 返回第一个元素,并在队列中删除
		for (String q : queue) {
			System.out.println(q);
		}
		System.out.println("===");
		System.out.println("element=" + queue.element()); // 返回第一个元素
		for (String q : queue) {
			System.out.println(q);
		}
		System.out.println("===");
		System.out.println("peek=" + queue.peek()); // 返回第一个元素
		for (String q : queue) {
			System.out.println(q);
		}
	}
}

BlockingQueue即阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞。被阻塞的情况主要有如下两种:

1. 当队列满了的时候进行入队列操作
2. 当队列空了的时候进行出队列操作

BlockingQueue四个接口,接口定义的方法如下:
Throws Exception	Special Value	Blocks	Times Out
插入	add(o)		offer(o)	put(o)	offer(o, timeout, timeunit)
移除	remove(o)	poll()		take()	poll(timeout, timeunit)
检查	element()	peek()		

这四套方法对应的特点分别是:

BlockingQueue 方法以四种形式出现,

对于不能立即满足但可能在将来某一时刻可以满足的操作,
这四种形式的处理方式不同:第一种是抛出一个异常,
第二种是返回一个特殊值(null 或 false,具体取决于操作),
第三种是在操作可以成功前,无限期地阻塞当前线程,
第四种是在放弃前只在给定的最大时间限制内阻塞


BlockingQueue的实现类

1. ArrayBlockingQueue
2. DelayQueue
3. LinkedBlockingQueue
4. PriorityBlockingQueue
5. SynchronousQueue



ArrayBlockingQueue是一个有边界的阻塞队列,它的内部实现是一个数组。有边界的意思是它的容量是有限的,我们必须在其初始化的时候指定它的容量大小,容量大小一旦指定就不可改变。

LinkedBlockingQueue阻塞队列大小的配置是可选的,如果我们初始化时指定一个大小,它就是有边界的,如果不指定,它就是无边界的。说是无边界,其实是采用了默认大小为Integer.MAX_VALUE的容量 
它的内部实现是一个链表。

PriorityBlockingQueue是一个没有边界的队列,它的排序规则和 java.util.PriorityQueue一样。需要注意,PriorityBlockingQueue中允许插入null对象。
所有插入PriorityBlockingQueue的对象必须实现 java.lang.Comparable接口,队列优先级的排序规则就是按照我们对这个接口的实现来定义的。

SynchronousQueue队列内部仅允许容纳一个元素。当一个线程插入一个元素后会被阻塞,除非这个元素被另一个线程消费。

DelayQueue
是一个无界的BlockingQueue,用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走。这种队列是有序的,
即队头对象的延迟到期的时间最长。如果没有任何延迟到期,那么就不会有任何头元素,并且poll将返回null(正因为这样,不能将
null放置到这种队列中).


DelayQueue阻塞的是其内部元素,DelayQueue中的元素必须实现 java.util.concurrent.Delayed接口,这个接口的定义非常简单:
public interface Delayed extends Comparable<Delayed> {
	long getDelay(TimeUnit unit);
}

getDelay()方法的返回值就是队列元素被释放前的保持时间,如果返回0或者一个负值,就意味着该元素已经到期需要被释放,此时DelayedQueue会通过其take()方法释放此对象。
从上面Delayed 接口定义可以看到,它还继承了Comparable接口,这是因为DelayedQueue中的元素需要进行排序,一般情况,我们都是按元素过期时间的优先级进行排序。

PriorityBlockingQueue示例:
public class PriorityElement implements Comparable<PriorityElement> {
	private int priority;// 定义优先级
	PriorityElement(int priority) {
		// 初始化优先级
		this.priority = priority;
	}
	@Override
	public int compareTo(PriorityElement o) {
		// 按照优先级大小进行排序
		return priority >= o.getPriority() ? 1 : -1;
	}
	public int getPriority() {
		return priority;
	}
	public void setPriority(int priority) {
		this.priority = priority;
	}
	@Override
	public String toString() {
		return "PriorityElement [priority=" + priority + "]";
	}
}

public class PriorityBlockingQueueExample {
	public static void main(String[] args) throws InterruptedException {
	    PriorityBlockingQueue<PriorityElement> queue = new PriorityBlockingQueue<PriorityElement>();
	    for (int i = 0; i < 5; i++) {
	        Random random=new Random();
	        PriorityElement ele = new PriorityElement(random.nextInt(10));
	        queue.put(ele);
	    }
	    while(!queue.isEmpty()){
	        System.out.println(queue.take());
	    }
	}
}


参考文章:http://blog.csdn.net/suifeng3051/article/details/48807423

管道流(pipeStream)是种特殊的流,用于在不同线程间传送数据,一个线程一端发送数据到管道,另外一个线程从输入管道读取
管道流有两种:
字符流:PipedReader、PipedWriter
字节流:PipedInputStrean、PipedOutputStram 

import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;

public class PipedWriteTest {

	public static class ThradPipedReaderA extends Thread {
		PipedReader pipedReader;
		public ThradPipedReaderA(PipedReader pipedReader) {
			this.pipedReader = pipedReader;
		}
		@Override
		public void run() {
			try {
				char[] chararray = new char[20];
				int readLenth = pipedReader.read(chararray);
				while (readLenth != -1) {
					String str = new String(chararray, 0, readLenth);
					System.out.println("读到的数据为:" + str);
					readLenth = pipedReader.read(chararray);
				}
				pipedReader.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	public static class ThradPipedWriteB extends Thread {
		PipedWriter pipedWriter;
		public ThradPipedWriteB(PipedWriter pipedWriter) {
			this.pipedWriter = pipedWriter;
		}
		@Override
		public void run() {
			try {
				for (int i = 0; i <= 10; i++) {
					pipedWriter.write("发送数据" + i);
				}
				pipedWriter.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	public static void main(String[] args) throws IOException {
		PipedReader pipedReader = new PipedReader();
		PipedWriter pipedWriter = new PipedWriter();
		pipedReader.connect(pipedWriter);// 做个链接才能通讯
		ThradPipedReaderA a = new ThradPipedReaderA(pipedReader);
		ThradPipedWriteB b = new ThradPipedWriteB(pipedWriter);
		a.start();
		b.start();
	}
}

猜你喜欢

转载自yangeoo.iteye.com/blog/2410992