17.并发类容器设计
并发类容器设计
1.ConcurrentHashMap:代替散列普通的hashTable,添加了复合操作支持。
private ConcurrentHashMap<String, Object> resultMap = new ConcurrentHashMap<String, Object>();
for (Map.Entry<String, Object> m : resultMap.entrySet()) {
count += (Long) m.getValue();
}
2.CopyOnWriteArrayList:代替了voctor,并发的CopyOnWriteArraySet,以及并发的queue。
3.ConcurrentLikedQueue:(高性能队列)、无阻塞形式、基于链表的无界队列,该队列不允许为空、先进先出原则。
package demo6;
import java.util.concurrent.ConcurrentLinkedQueue;
/**高性能队列、无阻塞
*/
public class DemoConcurrentLinkedQueue {
/**
* 说明:list与Queue的区别
* 1.队列先进先出
* 2.list集合
*/
/*
使用take()函数,如果队列中没有数据,则线程wait释放CPU,而poll()则不会等待,直接返回null;同样,空间耗尽时offer()函数不会等待,直接返回false,
而put()则会wait,因此如果你使用while(true)来获得队列元素,千万别用poll(),CPU会100%的.
*/
public static void main(String[] args){
ConcurrentLinkedQueue<String> mq = new ConcurrentLinkedQueue<String>();
mq.add("小明");
mq.add("王老吉");
mq.add("大宝");
mq.add("哈士奇");
System.err.println(mq.poll());//1.取出该元素并删除
System.err.println(mq.size());
System.err.println(mq.peek());//1.取出不删除
System.err.println(mq.size());
}
}
输出:
小明 3 王老吉 3
4.LinkedBlockingQueue:(阻塞形式队列)、连链表构成、采用分离锁、读写分离、无界队列、可并行生产、消费。
BlockingQueue<String> mq2 = new LinkedBlockingQueue<String>(5);//有界、无界
mq2.add("1+");
mq2.add("2+");
mq2.add("3+");
mq2.add("4+");
mq2.add("5+");
for (Iterator iterator = mq2.iterator();iterator.hasNext();){
String str = (String) iterator.next();
System.err.println(str);
}
List<String> list = new ArrayList<>();
System.err.println("批量获取:"+mq2.drainTo(list,3));
for (String s:list){
5.ArrayBlockingQueue:基于数组的实现阻塞形式队列、自定义长度、生产、消费不能并行执行,可先进先出、先进后出。
BlockingQueue<String> mq1 = new ArrayBlockingQueue<String>(3);
mq1.add("a");
mq1.put("b");
mq1.add("e");
6.PriorityBlockingQueue:基于优先级的阻塞形式,使用公平分离锁实现,优先级有comparable对象决定,实现此接口,没取一个队列排列一次队列
package demo6;
public 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;
}
@Override
public int compareTo(Task o) {
return this.id > o.id ? 1 : (this.id < o.id ? -1 : 0);
}
@Override
public String toString() {
return "Task{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
package demo6;
import java.util.concurrent.PriorityBlockingQueue;
public class DemoPriorityBlockingQueue {
public static void main(String[] args) throws InterruptedException {
PriorityBlockingQueue<Task> priorityBlockingQueue = new PriorityBlockingQueue<Task>();
/**
* 每取一个队列,就排一次序
*/
Task t1 = new Task();
t1.setId(3);
t1.setName(" 任务1");
Task t2 = new Task();
t2.setId(6);
t2.setName(" 任务2");
Task t3 = new Task();
t3.setId(1);
t3.setName(" 任务3");
priorityBlockingQueue.add(t1);
priorityBlockingQueue.add(t2);
priorityBlockingQueue.add(t3);
/* for (Task q:priorityBlockingQueue){
System.err.println(q.getId()+"\t"+q.getName());
}*/
System.err.println("容器:"+priorityBlockingQueue);
System.err.println(priorityBlockingQueue.poll().getId());
System.err.println("容器:"+priorityBlockingQueue);
System.err.println(priorityBlockingQueue.poll().getId());
System.err.println("容器:"+priorityBlockingQueue);
System.err.println(priorityBlockingQueue.poll().getId());
}
}
输出
容器:[Task{id=1, name=' 任务3'}, Task{id=6, name=' 任务2'}, Task{id=3, name=' 任务1'}] 1 容器:[Task{id=3, name=' 任务1'}, Task{id=6, name=' 任务2'}] 3 容器:[Task{id=6, name=' 任务2'}] 6
7.synchronizeQueue:无缓冲的队列,生产消费的数据直接被消费者offer,不可直接使用add方法,必须先take方法在前,调用处于阻塞状态,等待add()方法的通知。
package demo6;
import java.util.concurrent.SynchronousQueue;
public class DemoSynchronousQueue {
public static void main(String[] args) {
final SynchronousQueue<String> synchronousQueue = new SynchronousQueue<String>();
/**
* 不可直接使用add()方法,必须先有take方法在前调用(处于阻塞状态,等待add的通知激活),add()方法在后,
*/
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.err.println(synchronousQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "T1");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronousQueue.add("哈哈哈哈");
}
}, "T2");
t2.start();
}
}
8.delayQueue:带有延迟时间的队列。
package demo6;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public class WangMin implements Delayed {
private String name;
private String id;
/*结束时间*/
private long endTime;
public WangMin(String name, String id, long endTime) {
this.name = name;
this.id = id;
this.endTime = endTime;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public long getEndTime() {
return endTime;
}
public void setEndTime(long endTime) {
this.endTime = endTime;
}
private TimeUnit timeUnit = TimeUnit.SECONDS;
/*用来判断是否时间已经到期*/
@Override
public long getDelay(TimeUnit unit) {
return this.endTime - System.currentTimeMillis();
}
/*相互排序比较时间*/
@Override
public int compareTo(Delayed o) {
WangMin wangMin = (WangMin) o;
return this.getDelay(this.timeUnit) - wangMin.getDelay(this.timeUnit) > 0 ? 1 : 0;
}
}
package demo6;
import java.util.concurrent.DelayQueue;
public class WangBa implements Runnable{
private DelayQueue<WangMin> queue = new DelayQueue<WangMin>();
public boolean yinye = true;
public void startShangWang(String name, String id, int money) {
WangMin wangMin = new WangMin(name,id,1000*money+System.currentTimeMillis());
System.err.println("网络机器:"+wangMin.getName()+"\t身份证:"+wangMin.getId()+"\t金额:"+money+"\t开始上网。。。");
queue.add(wangMin);
}
public void endShangWang(WangMin wangMin) {
System.err.println("网络机器:"+wangMin.getName()+"\t身份证:"+wangMin.getId()+"\t下机了....");
}
@Override
public void run() {
while (yinye){
try {
WangMin min = queue.take();
endShangWang(min);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args){
System.err.println("网吧开始...");
WangBa wangBa = new WangBa();
Thread sw = new Thread(wangBa);
sw.start();
wangBa.startShangWang("亚瑟1","xdwdasdasda12324323",5);
wangBa.startShangWang("亚瑟2","xdwdasdasda12324323",20);
wangBa.startShangWang("亚瑟3","xdwdasdasda12324323",15);
}
}
输出:
网吧开始... 网络机器:亚瑟1 身份证:xdwdasdasda12324323 金额:5 开始上网。。。 网络机器:亚瑟2 身份证:xdwdasdasda12324323 金额:20 开始上网。。。 网络机器:亚瑟3 身份证:xdwdasdasda12324323 金额:15 开始上网。。。 网络机器:亚瑟1 身份证:xdwdasdasda12324323 下机了.... 网络机器:亚瑟3 身份证:xdwdasdasda12324323 下机了.... 网络机器:亚瑟2 身份证:xdwdasdasda12324323 下机了....
常用方法
1.add() 添加一个元素。
2.offer(队列,时间秒,时间范围单位)
3.poll()取出元素并删除,否返回null。
4.peck()取出,否返回false。
5.tace()取出,如果队列无数据直接释放cpu。
并发类:
1. ConcurrentLikedQueue 高性能、无阻塞、无界
2.BlockingQueue 阻塞形式队列