2014-03-18 91 views
3

我有一個收集器,用於搜索遊戲中的移動。我在遞歸搜索中進行搜索,以便從遊戲中獲得所有可能的移動。等待遞歸線程生成器

對於性能的原因,我使用一個線程池,並且每個找到的移動都會向池中添加一個新的線程,以延長舊的移動。

下面是一些代碼:

protected static List<Runnable> threads; 
private static ExecutorService threadPool; 

protected final synchronized void hookThread(Runnable thread) { 
     if (threadPool == null) { 
      threadPool = Executors.newFixedThreadPool(15); 
      threads = new ArrayList<Runnable>(); 
     } 
     threadPool.execute(thread); 
     threads.add(thread); 
    } 

protected abstract class GathererRunnable implements Runnable { 

    @Override 
    public final void run() { 
     onRun(); 
     threads.remove(this); 
    } 

    public abstract void onRun(); 

} 

這是父類的一個片段。現在來看這個孩子,它搜索這些動作。

private void extendMove(final byte[] stones, final ByteLayMove move) { 
    Runnable r = new GathererRunnable() { 

     @Override 
     public void onRun() { 
      // fancy search stuff 
      if (moveIsFound) 
       extendMove(...); 
     } 

    }; 
    hookThread(r); 
} 

現在的問題是,我不知道我應該如何等待線程完成。

我試圖使用一個int,它在線程創建和向下線程完成時進行計數,但是這也會導致過早的搜索流產。

如果有一個很好的方法來等待這些線程,你有一個想法嗎? 我已經想過一個BlockingQueue,但我不知道如何正確實現它。

問候凱文

+1

您是否使用了[的AtomicInteger(http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicInteger.html)或常規'int' ?後者不起作用,但第一個應該(使用方法'incrementAndGet'和'decrementAndGet')。 – vanOekel

+0

'ArrayList'線程安全嗎? –

回答

0

下面程序使用的BlockingQueue實現生產消費情況,可以在寫自己的實現中使用這種方法。

import java.util.concurrent.*; 
public class ThreadingExample { 

    public static void main(String args[]){ 
     BlockingQueue<Message> blockingQueue = new ArrayBlockingQueue<Message>(100); 
     ExecutorService exec = Executors.newCachedThreadPool(); 
     exec.execute(new Producer(blockingQueue)); 
     exec.execute(new Consumer(blockingQueue)); 
    } 

} 
class Message{ 
    private static int count=0; 
    int messageId; 
    Message(){ 
     this.messageId=count++; 
     System.out.print("message Id"+messageId+" Created "); 
    } 
} 
class Producer implements Runnable{ 

    private BlockingQueue<Message> blockingQueue; 
    Producer(BlockingQueue<Message> blockingQueue){ 
     this.blockingQueue=blockingQueue; 
    } 

    @Override 
    public void run(){ 
     while(!Thread.interrupted()){ 
      System.out.print("Producer Started"); 
      try { 
       blockingQueue.put(new Message()); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      System.out.println("Producer Done"); 
     } 
    } 
} 

class Consumer implements Runnable{ 
    private BlockingQueue<Message> blockingQueue; 
    Consumer(BlockingQueue<Message> blockingQueue){ 
     this.blockingQueue=blockingQueue; 
    } 

    @Override 
    public void run(){ 
     while(!Thread.interrupted()){ 
      System.out.print("Concumer Started"); 
      try{ 
       Message message = blockingQueue.take(); 
       System.out.print("message Id"+message.messageId+" Consumed "); 
      } 
      catch(InterruptedException e){ 
       e.printStackTrace(); 
      } 
      System.out.println("Concumer Done"); 
     } 
    } 
}