• Java并发编程 之 阻塞队列和CountDownLatch(转)


    前几天看到一个面试题目:有一个长度为2000的字符串,开三个线程去判断字符串中”u51”的个数。

    当时看到这个题目的时候,对并发编程是没有什么经验的,在实际项目多线程的应用也只有一两次。最近在恶补《Java并发编程的艺术》,对这个题目就有了解题的思路了。在这里记录一下对该题的解法和思路。

    一开始的时候,我能确定的是对“u51”个数相加是需要做同步处理,主要是如何去用三个线程去遍历这个字符串呢。需要保证索引index每个线程只能拿到一个。所以我这里引用了阻塞队列。这样每个线程去take的时候保持每个index是唯一的。

    因为最近才去看多线程编程,如果有错误的地方,希望路过的大虾能给指出。

    先对阻塞队列ArrayBlockingQueue一些方法进行说明

     

    CountDownLatch 不需要多说,初始设定一个值,每次调用countDown会导致值减一。countDownLatch.await()一直等待该值变为0才继续执行。

    import java.util.Scanner;
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.CountDownLatch;
    
    /**
     * Created by JinTX on 2017/9/28.
     */
    public class ThreadTest extends Thread{
    
        static String str;//记录字符串
        static int strLength = 0;//记录字符串的长度
        static int count = 0;//记录匹配成功字符串的个数,即"u51"的个数
        static ArrayBlockingQueue<Object> stringNumber = new ArrayBlockingQueue<Object>(10000);//用阻塞队列来放字符串的下标
    
        /*需要做同步处理,因为这里的count++并不是一个原子操作*/
        public static synchronized void countAdd(){
            count++;
        }
    
        /*匹配字符的方法*/
        public static boolean isStrFind(char a,char b,char c){
            if(a=='u' && b=='5' && c=='1'){
                return true;
            }else{
                return false;
            }
        }
    
        public static class MyRunnable implements Runnable{
    
            CountDownLatch countDownLatch;
    
            public MyRunnable(CountDownLatch countDownLatch){
                this.countDownLatch = countDownLatch;
            }
    
            @Override
            public void run() {
                try {
                /*这里我用的是poll,主要是因为take是阻塞的。即如果队列中没有
                下标可以拿的时候,就会一直等待。而用poll是不会阻塞的。
                会在拿不到的时候会返回null*/
                    Integer x = (Integer) stringNumber.poll();
                    if(x!=null) {
                    /*需要先判断x是不是null,不然为null执行x<strLength会报空指针*/
                        while (x!=null && x < strLength) {
                            if (x + 2 < strLength) {
                                char a = str.charAt(x);
                                char b = str.charAt(x + 1);
                                char c = str.charAt(x + 2);
                                /*一开始我用indexOF去判断但是结果一直是错的,
                                所以自己定义了一个方法*/
                                if (isStrFind(a, b, c)) {
                                    countAdd();
                                   System.out.println(Thread.currentThread() + ":" + x);
                                }
                            }
                            x = (Integer) stringNumber.poll(); 
                        }
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                /*运行结束,把计数器的个数减一**/
                    countDownLatch.countDown();
                }
            }
    
        }
    
    
        public static void main(String[] args) throws Exception{
            Scanner scanner = new Scanner(System.in);
            while(scanner.hasNext()){
                str = scanner.next();
                strLength = str.length();
    
                for(int i=0;i<strLength;i++){
                    stringNumber.put(i);
                }
                /*计数器,保证在计数器为0的时候才输出匹配中的字符串个数*/
                CountDownLatch countDownLatch = new CountDownLatch(3);
                MyRunnable myRunnable = new MyRunnable(countDownLatch);
                Thread thread1 = new Thread(myRunnable);
                Thread thread2 = new Thread(myRunnable);
                Thread thread3 = new Thread(myRunnable);
    
                thread1.start();
                thread2.start();
                thread3.start();
                /*等待所有的线程执行完毕*/
                countDownLatch.await();
                System.out.println("All 'u51' count num is: "+count);
            }
        }
    
    }

    运行结果:


    ————————————————
    版权声明:本文为CSDN博主「CallMeJiaGu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/MakeContral/article/details/78122769

  • 相关阅读:
    android apk 反编译
    js 读 xml 非ie 可以支持 chrome 浏览器 与 android webView
    php+mySQl 环境搭建
    Activity 生命周期
    div 隐藏 显示 占空间 不占空间
    android 异步加载
    android 文件操作
    透明 GridView 背景透明
    eclipse 版本理解
    WebKit 上的JS直接使用Java Bean
  • 原文地址:https://www.cnblogs.com/wangbin2188/p/16547989.html
Copyright © 2020-2023  润新知