2012-03-28 109 views
2

我正在尝试创建一个Java线程的简单队列,该线程允许一个循环(比如说一个包含10次迭代的for循环)一次迭代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 2015-07-21 12:40:06

回答

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中,特别是遗嘱执行人及的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 2015-10-13 00:20:20

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); 
}