zoukankan      html  css  js  c++  java
  • 线程应用:(九)阻塞队列的应用

    队列:先进先出

    1)ArrayBlockingQueue,固定大小队列

      当固定大小的队列满了时,可以选择以抛异常(Throws exception)、立马返回判断值(Special value)、阻塞(Blocks)中的1种形式进行操作。如下图。

      

    案例1:有2个线程从队列取数据,有1个线程往队列放数据。

    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class ArrayBlockTest {
        public static void main(String[] args) {
            ExecutorService service = Executors.newCachedThreadPool();
            final BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(3);
            
            for(int i=0;i<2;i++){        //有两个线程不停往队列里放数据
                final Integer data = i;
                service.execute(new Runnable() {
                    @Override
                    public void run() {
                        while(true){
                            try {
                                Thread.sleep((long)(Math.random()*1000));
                                System.out.println(Thread.currentThread().getName()+"准备放数据");
                                queue.put(data);    //队列如果满了,阻塞在这
                                System.out.println(Thread.currentThread().getName()+"已经放数据,目前队列数据数:"+queue.size());
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                });
            }
            
            service.execute(new Runnable() {
                @Override
                public void run() {
                    while(true){
                        try {
                            Thread.sleep(1000);    //注释掉看看效果
                            System.out.println(Thread.currentThread().getName()+"准备取数据");
                            queue.take();    //取的快,阻塞在这
                            System.out.println(Thread.currentThread().getName()+"已经取数据,目前队列数据数:"+queue.size());
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
        }
    }

    案例2:原本使用单线程,要16秒才能完成打印日志,现在启动4个线程分别取打印,只要4秒即可完成。

    思路:主线程把任务放到队列里,然后让其他线程自己去取。

    //阻塞队列结合线程使用案例
    public class ArrayBlockTest2 {
        public static void main(String[] args) throws InterruptedException {
            final BlockingQueue<String> queue = new ArrayBlockingQueue<String>(16);
            
            //同时开启4个线程去打印,让原来1个线程要打印16s,现在只要打印4s
            for(int i=0;i<4;i++){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        while(true){
                            try {
                                String log = queue.take();
                                parseLog(log);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }).start();
            }
            
            //主线程往队列放16个字符串
            for(int i=0;i<16;i++){
                final String log = ""+(i+1);
                queue.put(log);
            }
        }
        
        public static void parseLog(String log) throws InterruptedException{
            System.out.println(log+":"+(System.currentTimeMillis()/1000));
            Thread.sleep(1000);    //把打印时间设置为1s打印1次
        }
        
    }

    2)LinkedBlockingQueue,不固定大小队列

  • 相关阅读:
    给div添加disabled属性
    11个让你吃惊的 Linux 终端命令
    在 Linux 平台中调试 C/C++ 内存泄漏方法(转)
    在压缩话单中过滤指定IP的一个小脚本
    过滤IP地址的正则表达式
    【转】网络编程知识
    linux下软链接与硬链接及其区别
    函数式编程入门教程(转)
    suricate学习笔记1--初步认识(转)
    lsof命令详解(转)
  • 原文地址:https://www.cnblogs.com/zjxiang/p/9452262.html
Copyright © 2011-2022 走看看