2013-10-20 77 views
1

我有一堆我想通過線程池執行的runnables。但是,每個runnable還會將某些結果寫入某個文件。所以現在,Runnable的界面很簡單:執行程序中的每個線程的Java關聯對象

class MyRunnable implements Runnable { 
    ... 
    MyRunnable(BufferedWriter writer, Task t) { 
     this.writer = writer; 
     this.task = t; 
    } 

    public void run() { 
     ... 
     this.writer.write(SOME_DATA); 
    } 
} 

但是,我想要的是一個的BufferedWriter(換句話說,一個輸出文件),每個執行程序中的池線程的關聯。不過,我打電話使用ExecutorService.execute功能如下:

BufferedWriter[] writers = initialize to 20 BufferedWriters; 
ExecutorService executor = Executors.newFixedThreadPool(20); 
for (Task t : tasks) { 
    MyRunnable runnable = new MyRunnable(WHAT SHOULD GO HERE?, t) 
    executor.execute(runnable); 
} 

我不知道哪個線程執行將分配給運行給定的任務,所以我不知道我應該提供的BufferedWriter到可運行。我如何確保由ExecutorService管理的每個線程都與一個對象(在本例中爲BufferedWriter)相關聯?

回答

2

...我想要的是一個的BufferedWriter(換句話說一個輸出文件),每個執行程序中的池線程的關聯......

@ djechlin的約ThreadLocal回答是好但是它的問題在於當線程完成運行最後一項任務時,您無法訪問它們的BufferedWriterclose()

的備選答案可以在這裏看到:

Threadpool with persistent worker instances

在這裏面,我建議創建自己的任務BlockingQueue和分叉每線程任務,並使這些線程獲得任務你隊列。因此,線程運行方法將如下所示:

private final BlockingQueue<MyRunnable> queue = new ArrayBlockingQueue<>(); 
// if you want to shutdown your threads with a boolean 
private volatile boolean shutdown; 
... 

// threads running in the `ExecutorService` will be doing this run() method 
public void run() { 
    // this allows them to maintain state, in this case your writer 
    BufferedWriter writer = ...; 
    while (!shutdown && !Thread.currentThread.isInterrupted()) { 
     // they get their tasks from your own queue 
     MyRunnable runnable = queue.take(); 
     // if you are using a poison pill but you'll have to add X of them 
     if (runnable == STOP_OBJECT) { 
      break; 
     } 
     runnable.run(); 
    } 
    writer.close(); 
} 

告知線程何時完成有點棘手。您可以向隊列中添加「毒丸」對象,但您必須將相同數量的對象添加到隊列中,因爲有線程正在運行。

+0

lol,同時實現@ djechlin的答案我遇到了不能關閉編寫器的確切問題-.-因此,你推薦的基本上是管理我自己的線程池,並且每個線程都會拉動從同步源? – Jin

+0

那麼你仍然可以使用'ExecutorService'來管理總是推薦@Jin的線程。但是他們是否從你的'BlockingQueue'中抽出了他們的任務。 – Gray

+0

大聲笑我只是想到另一個更簡單但是哈克解決方案..運行「關閉緩衝作家」可以在一切完成後運行xD – Jin

3

這裏有一個類叫做ThreadLocal

例如

ThreadLocal<Type> t = new ThreadLocal<>() { 
    @Override protected Type initialValue() { 
     return new Type(Thread.currentThread.getName()); 
} 

這將每一個新的線程試圖訪問t時間懶惰初始化Type

我最後一次使用這個類只是在一個類中找出某個機器運行最好的線程數。 (答案通常是「內核數量」,但我想確保虛擬內核驅動這個數字而不是物理內核)。所以我寫了一個任務,其中每個線程只是垃圾郵件的一個AtomicInteger計數器。但是所有線程都在一個計數器上發生爭執,這造成了處理線程爭用的大量開銷,所以我創建了一個線程本地計數器,這樣線程就可以自己的計數器發送垃圾郵件,而不受其他線程的干擾。

由於大多數好的多線程設計可以避免這種情況,所以它的使用情況有些模糊,但當然有時間。

+0

太好了,就是我需要的。感謝您指出這個類:) – Jin

相關問題