java 多线程队列

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

 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的 Java 多线程队列实例,模拟队列实现排队叫号的过程: ```java import java.util.LinkedList; import java.util.Queue; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class QueueExample { private Queue<Integer> queue = new LinkedList<>(); private Lock lock = new ReentrantLock(); private int currentTicketNumber = 0; public void addCustomer() { lock.lock(); try { queue.offer(currentTicketNumber++); System.out.println("新顾客取得号码:" + (currentTicketNumber - 1) + ",当前队列长度:" + queue.size()); } finally { lock.unlock(); } } public void serveCustomer() { lock.lock(); try { Integer ticketNumber = queue.poll(); if (ticketNumber == null) { System.out.println("队列为空,无法叫号"); } else { System.out.println("叫到号码:" + ticketNumber + ",当前队列长度:" + queue.size()); } } finally { lock.unlock(); } } public static void main(String[] args) { final QueueExample queueExample = new QueueExample(); // 开启 5 个线程模拟 5 个顾客取号 for (int i = 0; i < 5; i++) { new Thread(new Runnable() { @Override public void run() { queueExample.addCustomer(); } }).start(); } // 开启 3 个线程模拟 3 个服务员叫号 for (int i = 0; i < 3; i++) { new Thread(new Runnable() { @Override public void run() { queueExample.serveCustomer(); } }).start(); } } } ``` 这个例子中,我们定义了一个 `QueueExample` 类,其中有一个 `queue` 队列,用于存储所有顾客的票号。我们使用 `ReentrantLock` 类来实现线程安全。在 `addCustomer` 方法中,我们通过 `offer` 方法往队列中添加一个顾客的票号,并输出当前队列长度以及新顾客的票号。在 `serveCustomer` 方法中,我们通过 `poll` 方法从队列中获取一个顾客的票号,并输出当前队列长度以及叫到的顾客的票号。 在 `main` 方法中,我们开启了 5 个线程模拟 5 个顾客取号,以及 3 个线程模拟 3 个服务员叫号。你可以运行这个例子来看一下具体的输出结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值