2012-03-28 9 views
2

私はJavaスレッドで単純なキューを作成しようとしています。これはループを10回反復してループを繰り返し、n(< 10)スレッドを一度に反復し、終了してから繰り返します。Javaスレッドのシンプルキュー

ここに私の問題を説明するための良い方法です:

for (int i = 1; i <= 10; i++) { 
    new Thread (do_some_work()); 

    if (no_available_threads) { 
     wait_until_available_threads(); 
    } 
} 

do_some_work() { 
    // do something that takes a long time 
} 

基本的に私がやりたいことは、こののコピーです:Thread and Queue

どのように私はこれが最も痛みのない方法を達成することができますか?

+0

http://docs.oracle.com/javase/7/docs/api/java/util /concurrent/BlockingQueue.htmlはそのような仕事には完璧です – bkowalczyyk

答えて

11

独自のロールアップではなく、Java 5 Executorsを使用します。以下のような何か:

ExecutorService service = Executors.newFixedThreadPool(10); 
// now submit our jobs 
service.submit(new Runnable() { 
    public void run() { 
     do_some_work(); 
    } 
}); 
// you can submit any number of jobs and the 10 threads will work on them 
// in order 
... 
// when no more to submit, call shutdown 
service.shutdown(); 
// now wait for the jobs to finish 
service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); 
0

他の人が推奨するようにしているjava.util.concurrent、特にexecutorおよびExecutorServiceの

2

は、エグゼキューの使用を参照してください。しかし、自分で楽しくしたいなら、このようなものを試してみてください。メモ帳に書きましたが、それ以外のものはすべて手に入れても捕らえなければならない例外がいくつかあります。メモ帳はコードエラーを捕まえていません。これは実際の解決策よりもコンセプトですが、一般に有用である可能性がある。

他の場所で
private ConcurrentLinkedQueue<MyThread> tQueue = 
      new ConcurrentLinkedQueue<MyThread>(); 

class MyThread extends Thread { 
    public Runnable doSomething; 

    public void run() { 
     // Do the real work. 
     doSomething(); 
     // Clean up and make MyThread available again. 
     tQueue.add(mythread); 
     // Might be able to avoid this synch with clever code. 
     // (Don't synch if you know no one's waiting.) 
     // (But do that later. Much later.) 
     synchronized (tQueue) { 
      // Tell them the queue is no longer empty. 
      tQueue.notifyAll(); 
     } 
    } 
} 

:また

// Put ten MyThreads in tQueue. 
for (int i = 0; i < 10; i++) tQueue.add(new MyThread()); 

// Main Loop. Runs ten threads endlessly. 
for (;;) { 
    MyThread t = tQueue.poll(); 
    if (t == null) { 
     // Queue empty. Sleep till someone tells us it's not. 
     do { 
      // There's a try-catch combo missing here. 
      synchonized(tQueue) { tQueue.wait() }; 
      t = tQueue.poll(); 
     } while (t == null) break; // Watch for fake alert! 
    } 
    t.doSomething = do_some_work; 
    t.start(); 
} 

、ConcurrentLinkedQueueの巧妙な使用に注意してください。 ArrayListやLinkedListのようなものを使うこともできますが、それらを同期させる必要があります。

+0

あなたはConcurrentLinkedQueueを使用していますが、なぜあなたはそれを同期していますか? – MikeB

0

クレートLogger.class

public class Logger extends Thread { 
    List<String> queue = new ArrayList<String>(); 
    private final int MAX_QUEUE_SIZE = 20; 
    private final int MAX_THREAD_COUNT = 10; 

    @Override 
    public void start() { 
     super.start(); 
     Runnable task = new Runnable() { 
      @Override 
      public void run() { 
       while (true) { 
        String message = pullMessage(); 
        Log.d(Thread.currentThread().getName(), message); 
        // Do another processing 
       } 
      } 
     }; 
     // Create a Group of Threads for processing 
     for (int i = 0; i < MAX_THREAD_COUNT; i++) { 
      new Thread(task).start(); 
     } 
    } 

    // Pulls a message from the queue 
    // Only returns when a new message is retrieves 
    // from the queue. 
    private synchronized String pullMessage() { 
     while (queue.isEmpty()) { 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
      } 
     } 
     return queue.remove(0); 
    } 

    // Push a new message to the tail of the queue if 
    // the queue has available positions 
    public synchronized void pushMessage(String logMsg) { 
     if (queue.size() < MAX_QUEUE_SIZE) { 
      queue.add(logMsg); 
      notifyAll(); 
     } 

    } 
} 

は、その後、あなたのメインクラスで怒鳴るのコードを挿入します。

Logger logger =new Logger(); 
logger.start(); 
for (int i=0; i< 10 ; i++) { 
    logger.pushMessage(" DATE : "+"Log Message #"+i); 
}