今天说一下这个大数据必学Java基础(六十七):DelayQueue深入了解

​DelayQueue深入了解

一、DelayQueue是什么

DelayQueue是一个无界的BlockingQueue,用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走。

当生产者线程调用put之类的方法加入元素时,会触发Delayed接口中的compareTo方法进行排序,也就是说队列中元素的顺序是按到期时间排序的,而非它们进入队列的顺序。排在队列头部的元素是最早到期的,越往后到期时间赿晚。

消费者线程查看队列头部的元素,注意是查看不是取出。然后调用元素的getDelay方法,如果此方法返回的值小0或者等于0,则消费者线程会从队列中取出此元素,并进行处理。如果getDelay方法返回的值大于0,则消费者线程wait返回的时间值后,再从队列头部取出元素,此时元素应该已经到期。

注意:不能将null元素放置到这种队列中。

二、DelayQueue能做什么

1. 淘宝订单业务:下单之后如果三十分钟之内没有付款就自动取消订单。
2. 饿了吗订餐通知:下单成功后60s之后给用户发送短信通知。

3. 关闭空闲连接。服务器中,有很多客户端的连接,空闲一段时间之后需要关闭之。

4. 缓存。缓存中的对象,超过了空闲时间,需要从缓存中移出。

5. 任务超时处理。在网络协议滑动窗口请求应答式交互时,处理超时未响应的请求等。

案例:

package com.lanson.test08;

import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * @author : Lansonli
 */
public class User implements Delayed {
    private int id;//用户id  private String name;//用户名字
  
    private long endTime;//结束时间

    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;
    }

    public long getEndTime() {
        return endTime;
    }

    public void setEndTime(long endTime) {
        this.endTime = endTime;
    }

    public User(int id, String name, long endTime) {
        this.id = id;
        this.name = name;
        this.endTime = endTime;
    }

    //只包装用户名字就可以
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }

    @Override
    public long getDelay(TimeUnit unit) {
        //计算剩余时间 剩余时间小于0 <=0  证明已经到期
        return this.getEndTime() - System.currentTimeMillis();
    }

    @Override
    public int compareTo(Delayed o) {
        //队列中数据 到期时间的比较
        User other = (User)o;
        return ((Long)(this.getEndTime())).compareTo((Long)(other.getEndTime()));
    }
}

compareTo:看谁先被移除

getDelay :看剩余时间

package com.lanson.test08;

import java.util.concurrent.DelayQueue;

/**
 * @author : Lansonli
 */
public class TestDelayQueue {
    //创建一个队列:
    DelayQueue<User> dq = new DelayQueue<>();

    //登录游戏:
    public void login(User user){
        dq.add(user);
        System.out.println("用户:[" + user.getId() +"],[" + user.getName() + "]已经登录,预计下机时间为:" + user.getEndTime() );
    }

    //时间到,退出游戏,队列中移除:
    public void logout(){
        //打印队列中剩余的人:
        System.out.println(dq);
        try {
            User user = dq.take();
            System.out.println("用户:[" + user.getId() +"],[" + user.getName() + "]上机时间到,自动退出游戏");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //获取在线人数:
    public int onlineSize(){
        return dq.size();
    }

    //这是main方法,程序的入口
    public static void main(String[] args) {
        //创建测试类对象:
        TestDelayQueue test = new TestDelayQueue();

        //添加登录的用户:
        test.login(new User(1,"张三",System.currentTimeMillis()+5000));
        test.login(new User(2,"李四",System.currentTimeMillis()+2000));
        test.login(new User(3,"王五",System.currentTimeMillis()+10000));
        //一直监控
        while(true){
            //到期的话,就自动下线:
            test.logout();
            //队列中元素都被移除了的话,那么停止监控,停止程序即可
            if(test.onlineSize() == 0){
                break;
            }
        }
    }
}

三、双端队列Deque

package com.lanson.test08;

import java.util.Collection;
import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;

/**
 * @author : Lansonli
 */
public class Test03 {
    //这是main方法,程序的入口
    public static void main(String[] args) {
        /*
        双端队列:
        Deque<E> extends Queue
        Queue一端放 一端取的基本方法  Deque是具备的
        在此基础上 又扩展了 一些 头尾操作(添加,删除,获取)的方法
         */
        Deque<String> d = new LinkedList<>() ;
        d.offer("A");
        d.offer("B");
        d.offer("C");
        System.out.println(d);//[A, B, C]

        d.offerFirst("D");
        d.offerLast("E");
        System.out.println(d);//[D, A, B, C, E]

        System.out.println(d.poll());
        System.out.println(d);//[A, B, C, E]

        System.out.println(d.pollFirst());
        System.out.println(d.pollLast());
        System.out.println(d);
    }
}

正文完