1. 程式人生 > >Java併發程式設計 之 阻塞佇列和CountDownLatch

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); } } }

執行結果:

這裡寫圖片描述