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