java队列方法很简单,就简单的 新增 add()/offer() 、 拿出 poll()、查看 peek(),这几种操作。 队列分为 阻塞的和非阻塞的,基本的用法都很简单,但是确是非常灵活。
Queue
add();//如果队列已满,会抛出错误
offer();//相当于add,如果队列已满,返回false
remove();//删除第一个元素,集合为空时调用抛出异常
poll();//删除第一个元素,集合为空时调用,返回null
peek();//查询队列头部元素,空时null
element();//查询队列头元素,空时报错
ConcurrentLinkedQueue 非阻塞队列
BlockingQueue 阻塞队列
新增了:
put();//如果满了,就会等待
take();//如果空了,就会等待
blockingQueue.offer("123",10,TimeUnit.MINUTES);//添加,如果添加不成功,10分钟后,程序阻塞
LinkedBQ 阻塞队列 列表
ArrayBQ 阻塞队列 数组
DelayQueue 执行定时任务,只能添加实现了 Delayed接口的对象
LinkedTransferQueue 等待消费者消费才能进行生产,有消费者时它会直接找消费者,没有就阻塞
transferQueue.transfer(); 与add/offer 生产者生产,如果无消费者,它会阻塞
SynchronousQueue 继承 TransferQueue,容量为0的队列,只能有put,只有消费者消费完之后才能进行put
非阻塞队列实现消费者和生产者模式
//非阻塞的队列
static Queue<String> linkedQueue = new ConcurrentLinkedQueue<>();//线程安全的队列
/**
* 简单的售票问题 非阻塞队列
*/
static void linkedQueueTest() {
System.out.println("初始化 共有100张票");
for (int i = 0 ;i < 100;i++ ){
// linkedQueue.add(i+"");//add 和 offer 都是往队列里面添加元素,add如果元素满了会报错,offer如果元素满了,会返回false
linkedQueue.offer(i+"");
}
//买票窗口
for (int i=0;i<5;i++){
//此线程对queue只有一个原子操作 poll,是线程安全的,不会产生多线程问题
new Thread(()->{
while (true){
String str = linkedQueue.poll();
if(str == null){
System.out.println("票已经卖完");
break;
}
System.out.print(str +",");
}
}).start();
}
}
双端队列实现 分类优先模式
//双端队列
static Deque<Integer> dequeQueue = new ConcurrentLinkedDeque<>();//线程安全的队列
/**
* 用双端队列实现 小孩优先
*/
public static void dequeTest(){
//初始化
for (int i=0;i<100;i++){
Integer randomInt = new Random().nextInt(100);
if(randomInt <= 14){
//小于14岁的,放在前面
dequeQueue.offerFirst(randomInt);
}else {
dequeQueue.offerLast(randomInt);
}
}
//出列
while (true){
Integer t = dequeQueue.poll();
if(t == null){
break;
}
System.out.print(t + ",");
}
}
用阻塞队列实现生产者-消费者模式
/**
* 用阻塞队列实现 消费者-生产者模式
* 生产者一直生产 ,直到仓库满了 就阻塞,消费者一直消费,直到仓库空了就阻塞
BlockingQueue 阻塞队列
新增了:
put();//如果满了,就会等待
take();//如果空了,就会等待
blockingQueue.offer("123",10,TimeUnit.MINUTES);//添加,如果添加不成功,10分钟后,程序阻塞
*/
public static void blockQueueTest(){
//阻塞队列
BlockingQueue blockingQueue = new ArrayBlockingQueue(10);
//三个线程在生产
for (int i=0;i<3;i++){
new Thread(()->{
while (true) {
try {
Thread.sleep(2000);
blockingQueue.put("good");//生产物品 如果满了,就等待消费
System.out.println("生产物品 size:"+blockingQueue.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
//消费者线程
for (int i=0;i<5;i++) {
new Thread(()->{
while (true) {
try {
Thread.sleep(3000);
blockingQueue.take();//阻塞消费,如果空,等待消费
System.out.println("消费了一个物品 size:"+blockingQueue.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
延时队列 实现定时任务
/**
* 延时队列 只能添加实现了 Delayed接口的对象,
* 可做定时任务的处理
*/
static void delayQueueTest(){
DelayQueue<MyDelayBead> delayQueue = new DelayQueue();
delayQueue.put(new MyDelayBead("1",3));//任务1 3秒后执行
delayQueue.put(new MyDelayBead("2",1));//任务2 1秒后执行
delayQueue.put(new MyDelayBead("3",5));//任务3 5秒后执行
while (true){
MyDelayBead myDelayBead = null;
try {
myDelayBead = delayQueue.take();
System.out.println("现在时间:"+System.currentTimeMillis()+" "+myDelayBead.toString());
if(delayQueue.size() == 0){
System.out.println("队列全部已经出列");
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
static class MyDelayBead implements Delayed {
int delaySecond;//延迟秒数
String task;//任务名
long createTime;//创建时间
@Override
public String toString() {
return "MyDelayBead{" +
"delaySecond=" + delaySecond +
", task='" + task + '\'' +
", createTime=" + createTime +" delay:"+getDelay(TimeUnit.MILLISECONDS)+
'}';
}
MyDelayBead(String task, int delaySecond){
this.task = task;
this.delaySecond = delaySecond;
this.createTime = System.currentTimeMillis();
}
/**
* 还有多长时间就可以往外拿了,注意需要使用现在的时间
*/
@Override
public long getDelay(TimeUnit unit) {
long targetTime = createTime + delaySecond * 1000;
return unit.convert( targetTime - System.currentTimeMillis() ,TimeUnit.MILLISECONDS);
// return delaySecond * 1000;
}
@Override
public int compareTo(Delayed o) {
if(this.getDelay(TimeUnit.MILLISECONDS ) > o.getDelay(TimeUnit.MILLISECONDS)){
return 1;
}else if(this.getDelay(TimeUnit.MILLISECONDS ) == o.getDelay(TimeUnit.MILLISECONDS)){
return 0;
}else{
return -1;
}
}
//getter and setter
public int getDelaySecond() {
return delaySecond;
}
public void setDelaySecond(int delaySecond) {
this.delaySecond = delaySecond;
}
public String getTask() {
return task;
}
public void setTask(String task) {
this.task = task;
}
public long getCreateTime() {
return createTime;
}
public void setCreateTime(long createTime) {
this.createTime = createTime;
}
}
上诉延迟队列的执行结果:
现在时间:1582008218242 MyDelayBead{delaySecond=1, task='2', createTime=1582008217240 delay:-2}
现在时间:1582008220240 MyDelayBead{delaySecond=3, task='1', createTime=1582008217240 delay:0}
现在时间:1582008222241 MyDelayBead{delaySecond=5, task='3', createTime=1582008217240 delay:-1}
队列全部已经出列
注意geDelay()重写时,需要结果调用的当前时间,意为距离当前还需要多久执行。
用TransferQueue实现 生产者-消费者模式,生产者需要等待消费者消费才生产
/**
* TransferQueue的生产者-消费者模式
* transferQueue.transfer(); 只有消费者消费才进行生产
*/
public static void transferQueueTest(){
//生产者 只有消费者消费才能进行生产
TransferQueue<String> transferQueue = new LinkedTransferQueue();
//生产者 2个
for (int i=0;i<2;i++){
new Thread(()->{
while (true) {
try {
//1秒生产一个
Thread.sleep(1000);
transferQueue.transfer("生产1个物品");//有消费者消费才进行生产
System.out.println("生产者生产 size:"+transferQueue.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
//消费者 5个
for (int i=0;i<1;i++){
new Thread(()->{
while (true) {
try {
Thread.sleep(5000);
transferQueue.take();
System.out.println("消费者消费 size:"+transferQueue.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}