Java併發程式設計 之 阻塞佇列和CountDownLatch
阿新 • • 發佈:2018-12-11
前幾天看到一個面試題目:有一個長度為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);
}
}
}
執行結果: