生活随笔
收集整理的這篇文章主要介紹了
线程池-生产消费者
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
求集合內兩兩字符串的編輯距離,先使用暴力方法,之后再介紹用kd樹的方法
主線程進行任務分發,將字符串依次放入線程池隊列中,線程池內的線程就計算這個字符串和所有字符串的編輯距離,然后將計算結果寫入blockqueue中,再起一個線程將blockqueue中的結果寫入磁盤中.這里有一個技巧,當處理完所有字符串,寫進程可能在將隊列中的結果寫入到磁盤也可能阻塞在take函數處。主線程就在隊列末尾放入一個結束標記,讀線程接收到這個標記之后就拋出異常結束了。
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;public class EditDistance{ExecutorService service ;List<String> ls;LinkedBlockingQueue<String> outque;class WordDist implements Comparable{public String word;public int dist;public WordDist(String wd, int d) {word = wd;dist = d;}public int compareTo(Object o) {return dist - ((WordDist)o).dist ;}public String toString () {return word + " " + dist;}}class Process implements Runnable {String name;public Process(String s) {name = s;}public void run() {PriorityQueue<WordDist> que = new PriorityQueue<WordDist>();for (int j = 0; j < ls.size(); ++j) {if (!name.equals(ls.get(j))) {que.add(new WordDist(ls.get(j), calcEditDist(name, ls.get(j))));}}StringBuilder sb = new StringBuilder();sb.append(name+"\t");int num = 20;int count = 0;while (que.peek() != null && count < num) {sb.append(que.poll() + " ");++count;}try {outque.put(sb.toString());} catch (InterruptedException e) {System.out.println(Thread.currentThread().getName() + " " + name);e.printStackTrace();}}}class Writer implements Runnable {PrintWriter pw;public Writer(String fn) {try {pw = new PrintWriter(fn);} catch (IOException e) {e.printStackTrace();return;}}@Overridepublic void run() {try {while (true) {String rst = outque.take();if (rst.equals("!!!POISON")) {throw new InterruptedException("meet a poison. over");}pw.println(rst);}} catch (InterruptedException e) {pw.close();System.out.println(e);System.out.println("Writer is over");}}}public int calcEditDist(String s1, String s2) {int [][]mat = new int[s1.length()+1][s2.length()+1];//mat[0][0] = 0;for (int i = 1; i <= s1.length(); ++i) mat[i][0] = i;for (int i = 1; i <= s2.length(); ++i) mat[0][i] = i;for (int i = 1; i <= s1.length(); ++i) {for (int j = 1; j <= s2.length(); ++j) {int repCost = 1;if (s1.charAt(i-1) == s2.charAt(j - 1)) {repCost = 0;}mat[i][j] = min(mat[i-1][j-1]+repCost, mat[i-1][j] + 1, mat[i][j-1] + 1);}}return mat[s1.length()][s2.length()];}private int min(int a, int b, int c) {int m = a;if (m > b) m = b;if (m > c) m = c;return m;}public void genCluster(String in, String out) {try {BufferedReader br = new BufferedReader (new InputStreamReader(new FileInputStream (in) ,"utf-8"));//PrintWriter pw = new PrintWriter(out, "utf-8");service = Executors.newFixedThreadPool(7);String line;ls = new ArrayList<String>();outque = new LinkedBlockingQueue<String>();//while ((line = br.readLine()) != null) {Scanner scan = new Scanner(line);scan.useDelimiter(" \\|\\|\\| ");ls.add(scan.next());}br.close();Thread writer = new Thread(new Writer(out));writer.start();for (int i = 0; i < ls.size(); ++i) {service.submit(new Process(ls.get(i)));}service.shutdown();//提交完任務之后就調用shutdown,不能再提交新任務try {service.awaitTermination(24, TimeUnit.HOURS);//再接著阻塞等待所有任務的結束} catch (InterruptedException e) {e.printStackTrace();System.out.println("main await error");}try {outque.put("!!!POISON");} catch (InterruptedException e) {e.printStackTrace();System.out.println("put poison error");}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) {// TODO Auto-generated method stubif (args.length != 2) {System.out.println("in out");return;}EditDistance dist = new EditDistance();dist.genCluster(args[0], args[1]);}}
service.awaitTermination(24, TimeUnit.HOURS);
這個函數出問題了,java多線程和c有個不同之處在于,只要有一個線程再跑著,只要不是后臺線程,即使main線程執行結束了,就是用jstack看不到main線程了,其他線程也會繼續執行
恩,上面的程序跑了不止24小時,main線程執行結束了,也用poison把寫線程結束了,只剩下生產者線程了.....
總結
以上是生活随笔為你收集整理的线程池-生产消费者的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。