并发的queue
1.ConcurrentLinkedQueue
代码实例:
package com.wq.队列;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* @author wangqiang
* @date 2018/12/19 18:28
*/
public class UseQueue {
public static void main(String[] args) {
ConcurrentLinkedQueue<String> q = new ConcurrentLinkedQueue<>();
q.offer("a");
q.offer("b");
q.offer("c");
q.offer("d");
q.add("e"); //offer和add作用一样
System.out.println(q.size());
System.out.println(q.poll());//取头元素,会删除元素
System.out.println(q.size());
System.out.println(q.peek());//取头元素,不会删除元素
System.out.println(q.size());
}
}
输出结果:
2.BlockingQueue接口
代码实例
package com.wq.队列;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
/**
* @author wangqiang
* @date 2018/12/19 18:28
*/
public class UseQueue {
public static void main(String[] args) throws InterruptedException {
ArrayBlockingQueue<String> q = new ArrayBlockingQueue<String>(5);
q.put("a");
q.add("b");
q.add("c");
q.add("d");
q.add("e");
boolean a = q.offer("a", 2, TimeUnit.SECONDS);//2秒之内加成功就true,不成功就false
System.out.println(a);
}
}
输出结果:
false
如果不这么写,用add()会抛异常。 队列满了。长度改为6,则输出true
LinkedBlockingQueue
LinkedBlockingQueue<String> link = new LinkedBlockingQueue<>();
link.offer("a");
link.offer("b");
link.offer("c");
link.offer("d");
link.offer("e");
link.add("f");
// System.out.println(link.size());
List<String> list = new ArrayList<>();
//表示取三个元素放在心的集合里
System.out.println(link.drainTo(list,3));
System.out.println(list.size());
for (String s : list) {
System.out.println(s);
}
输出结果
3
3
a
b
c
LinkedBlockingQueue可以自定义长度,也可以不定义。 draint方法可以批量取元素放在指定的集合里面
加元素的 会new PriorityQueue需要实现comparable接口,自定义优先级
优先级队列例子:
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 task) {
return this.id>task.id?1:(this.id<task.id?-1:0);
//return this.id-task.id;
}
@Override
public String toString() {
return "Task{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
public class UsePriorityBlockQueue {
public static void main(String[] args) throws InterruptedException {
PriorityBlockingQueue<Task> q = new PriorityBlockingQueue<Task>();
Task t1 = new Task();
t1.setId(3);
t1.setName("任务3");
Task t2 = new Task();
t2.setId(4);
t2.setName("任务4");
Task t3 = new Task();
t3.setId(2);
t3.setName("任务2");
q.add(t1);
q.add(t2);
q.add(t3);
System.out.println("容器:"+q);
System.out.println(q.take().getId());
System.out.println("容器:"+q);
System.out.println(q.take().getId());
}
}
运行结果:
容器:[Task{id=2, name='任务2'}, Task{id=4, name='任务4'}, Task{id=3, name='任务3'}]
2
容器:[Task{id=3, name='任务3'}, Task{id=4, name='任务4'}]
3
分析:发现第一次输出的时候并没有按照Id的大小进行排序。 调查资料发现,该队列可能是按选择排序的,按照定义的优先级,每次调用take()或poll()会重新进行排序,此例子会把最小的id排在前面。由输出结果得出输出是没错的。。
SynchronousQueue队列:
该对列是没有任何容量的
SynchronousQueue<String> q = new SynchronousQueue<>();
q.add("33");
这样会报错
上面的代码是没有问题的,add方法并不是往容器里面加元素,直接给了阻塞着的take方法了。
delayQueue
public class WangBa implements Runnable{
private DelayQueue<Wangmin> queue = new DelayQueue<Wangmin>();
public boolean yinye =true;
public void shangji(String name,String id,int money) {
Wangmin man = new Wangmin(name,id,1000*money+System.currentTimeMillis());
System.out.println("网名:"+man.getName()+"身份证:"+man.getId()+"交钱"+money+"块,开始上机");
this.queue.add(man);
}
public void xiaji(Wangmin man) {
System.out.println("网名:"+man.getName()+"身份证:"+man.getId()+"时间到下机");
}
@Override
public void run() {
while(yinye) {
try {
Wangmin man = queue.take();
xiaji(man);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
System.out.println("网吧开始营业");
WangBa wangBa = new WangBa();
Thread shangwang = new Thread(wangBa);
shangwang.start();
wangBa.shangji("路人甲", "123", 10);
wangBa.shangji("路人乙", "234", 20);
wangBa.shangji("路人丙", "345", 30);
}
}
public class Wangmin implements Delayed {
private String name;
private String id;
private long endTime;
private TimeUnit timeUnit = TimeUnit.SECONDS;
public Wangmin(String name,String id ,long endTime) {
this.name=name;
this.id=id;
this.endTime=endTime;
}
public String getName() {
return name;
}
public String getId() {
return id;
}
@Override
public int compareTo(Delayed o) {
Wangmin w=(Wangmin) o;
return this.getDelay(this.timeUnit)-w.getDelay(this.timeUnit)>0?1:0;
}
//用来判断是否到了截止时间
@Override
public long getDelay(TimeUnit unit) {
return endTime-System.currentTimeMillis();
}
}
输出结果:
网吧开始营业
网名:路人甲身份证:123交钱10块,开始上机
网名:路人乙身份证:234交钱20块,开始上机
网名:路人丙身份证:345交钱30块,开始上机
网名:路人甲身份证:123时间到下机
网名:路人乙身份证:234时间到下机
网名:路人丙身份证:345时间到下机
可以看看这篇文章
https://www.cnblogs.com/sunzhenchao/p/3515085.html
在学习Java 多线程并发开发过程中,了解到DelayQueue类的主要作用:是一个无界的BlockingQueue,用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走。这种队列是有序的,即队头对象的延迟到期时间最长。注意:不能将null元素放置到这种队列中。
Delayed,一种混合风格的接口,用来标记那些应该在给定延迟时间之后执行的对象。此接口的实现必须定义一个 compareTo 方法,该方法提供与此接口的 getDelay 方法一致的排序。
在网上也看到两个示例,但这两个示例个人在实际运行时均没有达到满足业务场景的效果,因而对其进行了修改,供大家参考讨论。
业务场景一:多考生考试
该场景来自于http://ideasforjava.iteye.com/blog/657384,模拟一个考试的日子,考试时间为120分钟,30分钟后才可交卷,当时间到了,或学生都交完卷了考试结束。
这个场景中几个点需要注意:
- 考试时间为120分钟,30分钟后才可交卷,初始化考生完成试卷时间最小应为30分钟
- 对于能够在120分钟内交卷的考生,如何实现这些考生交卷
- 对于120分钟内没有完成考试的考生,在120分钟考试时间到后需要让他们强制交卷
- 在所有的考生都交完卷后,需要将控制线程关闭
实现思想:用DelayQueue存储考生(Student类),每一个考生都有自己的名字和完成试卷的时间,Teacher线程对DelayQueue进行监控,收取完成试卷小于120分钟的学生的试卷。当考试时间120分钟到时,先关闭Teacher线程,然后强制DelayQueue中还存在的考生交卷。每一个考生交卷都会进行一次countDownLatch.countDown(),当countDownLatch.await()不再阻塞说明所有考生都交完卷了,而后结束考试。
package com.my.base.concurrent.delayQueue;
import java.util.Iterator;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
/**
*this project is created for my partactice.
*In the project I will write the mybatis by myself
*
*2014-1-10 下午9:43:48
*@author 孙振超 mychaoyue2011@163.com
*/
public class Exam {
/**
*
*2014-1-10 下午9:43:48 by 孙振超
*
*@param args
*void
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
int studentNumber = 20;
CountDownLatch countDownLatch = new CountDownLatch(studentNumber+1);
DelayQueue< Student> students = new DelayQueue<Student>();
Random random = new Random();
for (int i = 0; i < studentNumber; i++) {
students.put(new Student("student"+(i+1), 30+random.nextInt(120),countDownLatch));
}
Thread teacherThread =new Thread(new Teacher(students));
students.put(new EndExam(students, 120,countDownLatch,teacherThread));
teacherThread.start();
countDownLatch.await();
System.out.println(" 考试时间到,全部交卷!");
}
}
class Student implements Runnable,Delayed{
private String name;
private long workTime;
private long submitTime;
private boolean isForce = false;
private CountDownLatch countDownLatch;
public Student(){}
public Student(String name,long workTime,CountDownLatch countDownLatch){
this.name = name;
this.workTime = workTime;
this.submitTime = TimeUnit.NANOSECONDS.convert(workTime, TimeUnit.NANOSECONDS)+System.nanoTime();
this.countDownLatch = countDownLatch;
}
@Override
public int compareTo(Delayed o) {
// TODO Auto-generated method stub
if(o == null || ! (o instanceof Student)) return 1;
if(o == this) return 0;
Student s = (Student)o;
if (this.workTime > s.workTime) {
return 1;
}else if (this.workTime == s.workTime) {
return 0;
}else {
return -1;
}
}
@Override
public long getDelay(TimeUnit unit) {
// TODO Auto-generated method stub
return unit.convert(submitTime - System.nanoTime(), TimeUnit.NANOSECONDS);
}
@Override
public void run() {
// TODO Auto-generated method stub
if (isForce) {
System.out.println(name + " 交卷, 希望用时" + workTime + "分钟"+" ,实际用时 120分钟" );
}else {
System.out.println(name + " 交卷, 希望用时" + workTime + "分钟"+" ,实际用时 "+workTime +" 分钟");
}
countDownLatch.countDown();
}
public boolean isForce() {
return isForce;
}
public void setForce(boolean isForce) {
this.isForce = isForce;
}
}
class EndExam extends Student{
private DelayQueue<Student> students;
private CountDownLatch countDownLatch;
private Thread teacherThread;
public EndExam(DelayQueue<Student> students, long workTime, CountDownLatch countDownLatch,Thread teacherThread) {
super("强制收卷", workTime,countDownLatch);
this.students = students;
this.countDownLatch = countDownLatch;
this.teacherThread = teacherThread;
}
@Override
public void run() {
// TODO Auto-generated method stub
teacherThread.interrupt();
Student tmpStudent;
for (Iterator<Student> iterator2 = students.iterator(); iterator2.hasNext();) {
tmpStudent = iterator2.next();
tmpStudent.setForce(true);
tmpStudent.run();
}
countDownLatch.countDown();
}
}
class Teacher implements Runnable{
private DelayQueue<Student> students;
public Teacher(DelayQueue<Student> students){
this.students = students;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
System.out.println(" test start");
while(!Thread.interrupted()){
students.take().run();
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}