BlockingQueue
- 通常用链表或者数组实现
- 一般而言队列具备FIFO先进先出的特性,当然也有双端队列(Deque)优先级队列
- 主要操作:入队(EnQueue)与出队(Dequeue)
1、ArrayBlockingQueue 由数组支持的有界队列
队列基于数组实现,容量大小在创建ArrayBlockingQueue对象时已定义好(默认创建非公平锁)
import bean.Ball;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ArrayBlockingQueueTest {
/**
* 创建容量大小为1的有界队列
*/
private BlockingQueue<Ball> blockingQueue = new ArrayBlockingQueue<Ball>(1);
/**
* 队列大小
* @return
*/
public int queueSize(){
return blockingQueue.size();
}
/**
* 将球放入队列当中,生产者
* @param ball
* @throws InterruptedException
*/
public void produce(Ball ball) throws InterruptedException{
blockingQueue.put(ball);
}
/**
* 将球从队列当中拿出去,消费者
* @return
*/
public Ball consume() throws InterruptedException {
return blockingQueue.take();
}
public static void main(String[] args){
final ArrayBlockingQueueTest box = new ArrayBlockingQueueTest();
ExecutorService executorService = Executors.newCachedThreadPool();
/**
* 往箱子里面放入乒乓球
*/
executorService.submit(new Runnable() {
@Override
public void run() {
int i = 0;
while (true){
Ball ball = new Ball();
ball.setNumber("乒乓球编号:"+i);
ball.setColor("yellow");
try {
System.out.println(System.currentTimeMillis()+ ":准备往箱子里放入乒乓球:--->"+ball.getNumber());
box.produce(ball);
System.out.println(System.currentTimeMillis()+ ":往箱子里放入乒乓球:--->"+ball.getNumber());
System.out.println("put操作后,当前箱子中共有乒乓球:--->" + box.queueSize() + "个");
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
}
});
/**
* consumer,负责从箱子里面拿球出来
*/
executorService.submit(new Runnable() {
@Override
public void run() {
while (true){
try {
System.out.println(System.currentTimeMillis()+ "准备到箱子中拿乒乓球:--->");
Ball ball = box.consume();
System.out.println(System.currentTimeMillis()+ "拿到箱子中的乒乓球:--->"+ball.getNumber());
System.out.println("take操作后,当前箱子中共有乒乓球:--->" + box.queueSize() + "个");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
}
2、LinkedBlockingQueue 由链接节点支持的可选有界队列
3、PriorityBlockingQueue 由优先级堆支持的无界优先级队列
4、DelayQueue 由优先级堆支持的、基于时间的调度队列由优先级堆支持的、基于时间的调
度队列,内部基于无界队列PriorityQueue实现,而无界队列基于数组的扩容实现。
应用场景: 电影票 (要求:入队的对象必须要实现Delayed接口,而Delayed集成自Comparable接口)
/**
* 延期队列
*/
public class DelayedQueueTest {
public static void main(String[] args) {
DelayQueue<MovieTiket> delayQueue = new DelayQueue<MovieTiket>();
MovieTiket tiket = new MovieTiket("电影票0",10000);
delayQueue.put(tiket);
MovieTiket tiket1 = new MovieTiket("电影票1",5000);
delayQueue.put(tiket1);
MovieTiket tiket2 = new MovieTiket("电影票2",8000);
delayQueue.put(tiket2);
System.out.println("message:--->入队完毕");
while( delayQueue.size() > 0 ){
try {
tiket = delayQueue.take();
System.out.println("电影票出队:"+tiket.getMsg());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
==
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public class MovieTiket implements Delayed {
//延迟时间
private final long delay;
//到期时间
private final long expire;
//数据
private final String msg;
//创建时间
private final long now;
==get set
/**
* @param msg 消息
* @param delay 延期时间
*/
public MovieTiket(String msg , long delay) {
this.delay = delay;
this.msg = msg;
expire = System.currentTimeMillis() + delay; //到期时间 = 当前时间+延迟时间
now = System.currentTimeMillis();
}
/**
* @param msg
*/
public MovieTiket(String msg){
this(msg,1000);
}
public MovieTiket(){
this(null,1000);
}
/**
* 获得延迟时间 用过期时间-当前时间,时间单位毫秒
* @param unit
* @return
*/
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(this.expire
- System.currentTimeMillis() , TimeUnit.MILLISECONDS);
}
/**
* 用于延迟队列内部比较排序 当前时间的延迟时间 - 比较对象的延迟时间
* 越早过期的时间在队列中越靠前
* @param delayed
* @return
*/
@Override
public int compareTo(Delayed delayed) {
return (int) (this.getDelay(TimeUnit.MILLISECONDS)
- delayed.getDelay(TimeUnit.MILLISECONDS));
}
@Override
public String toString() {
return "MovieTiket{" +
"delay=" + delay +
", expire=" + expire +
", msg='" + msg + '\'' +
", now=" + now +
'}';
}
}
HashMap
- Jdk7-HashMap的扩容【临界值threshold=16*0.75】产生死锁问题的分析(在多线程场景下,扩容期间存在节点位置互换指针引用的问题)【会产生数据丢失问题】
- Jdk8-HashMap的扩容无死锁的过程优化 ,【会产生数据丢失问题】
ConcurrentHashMap
jdk1.7分段锁,reentranlock
jdk1.8使用synchroniezd 同步块