BlockingQueue
synchronousQueue学习
公平模式:
SynchronousQueue会采用公平锁,并配合一个FIFO队列来阻塞多余的生产者和消费者,从而体系整体的公平策略;
非公平模式(SynchronousQueue默认):
SynchronousQueue采用非公平锁,同时配合一个LIFO队列来管理多余的生产者和消费者,而后一种模式,如果生产者和消费者的处理速度有差距,则很容易出现饥渴的情况,即可能有某些生产者或者是消费者的数据永远都得不到处理。
注意:
(1)不能在同步队列上进行 peek,因为仅在试图要取得元素时,该元素才存在;
(2)除非另一个线程试图移除某个元素,否则也不能(使用任何方法)添加元素;
(3)不能迭代队列
(4)该队列的头是尝试添加到队列的首个已排队插入线程的元素;如果没有这样的已排队线程,则没有可用于移除的元素并且pool方法将返回null
(5)不允许 null 元素
对于其他 Collection 方法(例如 contains)SynchronousQueue 作为一个空集合。
(6)同步队列类似于传递性的设计,即一个线程中运行的对象要将某些信息/事件/任务传递给另一个线程中运行的对象-->同步
(7)SynchronousQueue构造方法中可指定fairness的策略.如果fair,则等待线程以FIFO的顺序竞争访问;否则顺序是未指定的
-
SynchronousQueue方法
-
iterator() 永远返回空,因为里面没东西。
-
peek() 永远返回null。
-
put() 往queue放进去一个element以后就一直wait直到有其他thread进来把这个element取走。
-
offer() 往queue里放一个element后立即返回,如果碰巧这个element被另一个thread取走了,offer方法返回true,认为offer成功;否则返回false。
-
offer(2000, TimeUnit.SECONDS) 往queue里放一个element但是等待指定的时间后才返回,返回的逻辑和offer()方法一样。
-
take() 取出并且remove掉queue里的element(认为是在queue里的。。。),取不到东西他会一直等。
-
poll() 取出并且remove掉queue里的element(认为是在queue里的。。。),只有到碰巧另外一个线程正在往queue里offer数据或者put数据的时候,该方法才会取到东西。否则立即返回null。
-
poll(2000, TimeUnit.SECONDS) 等待指定的时间然后取出并且remove掉queue里的element,其实就是再等其他的thread来往里塞。
-
isEmpty()永远是true。
-
remainingCapacity() 永远是0。
-
remove()和removeAll() 永远是false。
注意:
(1)SynchronousQueue中没有空间,那么资源会会以最快的方式从生产者传递给消费者。
(2)SynchronousQueue中维护着生产者和消费者线程队列,既然有队列,同样就有公平性和非公平性特性,公平性保证正在等待的插入线 程或者移除线程以FIFO的顺序传递资源
优先级队列PriorityBlockingQueue
规则是:当前和其他对象比较,如果compare方法返回负数,那么在队列里面的优先级就比较搞。
/**
*
*
* QueenTest
* 创建人:LBM
* 时间:2016年11月29日-上午10:54:16
* @version 1.0.0
*
*/
public class QueenTest {
public static void main(String[] args) {
PriorityBlockingQueue<Task> queue = new PriorityBlockingQueue<Task>();//创建一个优先级队列
Task task1 = new Task();
task1.setId(50);
Task task2 = new Task();
task2.setId(30);
Task task3 = new Task();
task3.setId(23);
Task task4 = new Task();
task4.setId(100);
// 像优先级队列中插入三个对象
queue.put(task1);
queue.put(task2);
queue.put(task3);
queue.put(task4);
for (Task task : queue) {
System.out.println("循环打印队列,查看队列顺序"+task.getId());
}
try {
System.out.println("每次take后,查看队列顺序"+queue);
System.out.println(queue.take().getId());
System.out.println("每次take后,查看队列顺序"+queue);
System.out.println(queue.take().getId());
System.out.println("每次take后,查看队列顺序"+queue);
System.out.println(queue.take().getId());
System.out.println("每次take后,查看队列顺序"+queue);
System.out.println(queue.take().getId());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//创建一个类实现Comparable方法
class Task implements Comparable<Task>{
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//实现compareTo方法
public int compareTo(Task task) {
//当新元素的id小于旧元素的时候,优先级比较高
if (task.id > this.id) {
return -1;
}
else if (task.id < this.id) {
return 1;
}else {
return 0;
}
}
//重写toString方法
@Override
public String toString() {
// TODO Auto-generated method stub
return this.id+"";
}
}
打印结果我们知道我们插入的这组数据,数据最小的优先级越高,按照我们的想法,那我们存储的队列顺序应该是【23,30,50,100】但是真实的顺序却是【23,50,30,100】这是为什么呢 ?