前几天看到一个面试题目:有一个长度为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);
}
}
}
运行结果: