• BlockingQueue介绍及使用


    1.BlockingQueue队列和平常队列一样都可以用来作为存储数据的容器,但有时候在线程当中
    涉及到数据存储的时候就会出现问题,而BlockingQueue是空的话,如果一个线程要从BlockingQueue
    里取数据的时候,该线程将会被阻断,并进入等待状态,直到BlockingQueue里面有数据存入了后,就会
    唤醒线程进行数据的去除。若BlockingQueue是满的,如果一个线程要将数据存入BlockQueue,该线程
    将会被阻断,并进入等待状态,直到BlcokQueue里面的数据被取出有空间后,线程被唤醒后在将数据存入、
     
    2.主要涉及的方法:
        BlockingQueue 方法以四种形式出现,对于不能立即满足但可能在将来某一时刻可以满足的操作,这四种形式的处理方式不同:第一种是抛出一个异常,第二种是返回一个特殊值(null 或 false,具体取决于操作),第三种是在操作可以成功前,无限期地阻塞当前线程,第四种是在放弃前只在给定的最大时间限制内阻塞。下表中总结了这些方法:
     
    抛出异常 特殊值 阻塞 超时
    插入 add(e) offer(e) put(e) offer(e, time, unit)
    移除 remove() poll() take() poll(time, unit)
    检查 element() peek() 不可用 不可用

    3.BlockingQueue定义的常用方法详解: 
            1)add(anObject):把anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则报异常 
            2)offer(anObject):表示如果可能的话,将anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则返回false. 
            3)put(anObject):把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里面有空间再继续. 
            4)poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,取不到时返回null 
            5)take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到Blocking有新的对象被加入为止 
        2.BlockingQueue有四个具体的实现类,根据不同需求,选择不同的实现类 
            1)ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小.其所含的对象是以FIFO(先入先出)顺序排序的. 
            2)LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的 BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含 的对象是以FIFO(先入先出)顺序排序的 
            3)PriorityBlockingQueue:类似于LinkedBlockQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数的Comparator决定的顺序. 
            4)SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的. 
        3.LinkedBlockingQueue和ArrayBlockingQueue比较起来,它们背后所用的数据结构不一样,导致 LinkedBlockingQueue的数据吞吐量要大于ArrayBlockingQueue,但在线程数量很大时其性能的可预见性低于 ArrayBlockingQueue.     

      在网上找到两个例子  :

    package com.thread;
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.BlockingQueue;
    
    public class BlockingQueueTest {
        public static void main(String[] args) {
            final BlockingQueue queue = new ArrayBlockingQueue(3);
            for(int i=0;i<2;i++){
                new Thread(){
                    public void run(){
                        while(true){
                            try {
                                Thread.sleep((long)(Math.random()*1000));
                                System.out.println(Thread.currentThread().getName() + "准备放数据!");                            
                                queue.put(1);
                                System.out.println(Thread.currentThread().getName() + "已经放了数据," +                             
                                            "队列目前有" + queue.size() + "个数据");
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
    
                        }
                    }
                    
                }.start();
            }
            
            new Thread(){
                public void run(){
                    while(true){
                        try {
                            //将此处的睡眠时间分别改为100和1000,观察运行结果
                            Thread.sleep(1000);
                            System.out.println(Thread.currentThread().getName() + "准备取数据!");
                            queue.take();
                            System.out.println(Thread.currentThread().getName() + "已经取走数据," +                             
                                    "队列目前有" + queue.size() + "个数据");                    
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                
            }.start();            
        }
    }
    

      ***********************************

    public class BlockingQueueCondition {
    
        public static void main(String[] args) {
            ExecutorService service = Executors.newSingleThreadExecutor();
            final Business3 business = new Business3();
            service.execute(new Runnable(){
    
                public void run() {
                    for(int i=0;i<50;i++){
                        business.sub();
                    }
                }
                
            });
            
            for(int i=0;i<50;i++){
                business.main();
            }
        }
    
    }
    
    class Business3{
        BlockingQueue subQueue = new ArrayBlockingQueue(1);
        BlockingQueue mainQueue = new ArrayBlockingQueue(1);
        //这里是匿名构造方法,只要new一个对象都会调用这个匿名构造方法,它与静态块不同,静态块只会执行一次,
        //在类第一次加载到JVM的时候执行
        //这里主要是让main线程首先put一个,就有东西可以取,如果不加这个匿名构造方法put一个的话程序就死锁了
        {
            try {
                mainQueue.put(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        public void sub(){
            try
            {
                mainQueue.take();
                for(int i=0;i<10;i++){
                    System.out.println(Thread.currentThread().getName() + " : " + i);
                }
                subQueue.put(1);
            }catch(Exception e){
    
            }
        }
        
        public void main(){
            
            try
            {
                subQueue.take();
                for(int i=0;i<5;i++){
                    System.out.println(Thread.currentThread().getName() + " : " + i);
                }
                mainQueue.put(1);
            }catch(Exception e){
            }        
        }
    }
    

      

  • 相关阅读:
    JavaScript基础
    CSS基础
    HTML基础
    LeetCode OJ:Subsets II(子集II)
    LeetCode OJ:Combination Sum III(组合之和III)
    LeetCode OJ:Minimum Size Subarray Sum(最小子数组的和)
    LeetCode OJ:House Robber(住宅窃贼)
    LeetCode OJ:Minimum Path Sum(最小路径和)
    LeetCode OJ:Minimum Depth of Binary Tree(二叉树的最小深度)
    LeetCode OJ:Rotate Array(倒置数组)
  • 原文地址:https://www.cnblogs.com/ganchuanpu/p/7758485.html
Copyright © 2020-2023  润新知