java Java线程简单队列

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9916264/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 22:53:28  来源:igfitidea点击:

Java thread simple queue

javamultithreadingqueue

提问by ioni

I'm trying to create a simple queue with Java Thread that would allow a loop, say a for loop with 10 iterations, to iterate n (< 10) threads at a time and wait until those threads are finished before continuing to iterate.

我正在尝试使用 Java 线程创建一个简单的队列,该队列将允许循环,例如具有 10 次迭代的 for 循环,一次迭代 n (< 10) 个线程并等到这些线程完成后再继续迭代。

Here's a better way to illustrate my problem:

这是说明我的问题的更好方法:

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
}

Basically what I want to do is a copy of this: Thread and Queue

基本上我想做的是一个副本:线程和队列

How can I achieve this the most painless way?

我怎样才能以最无痛的方式实现这一目标?

回答by Gray

I would use the Java 5 Executorsinstead of rolling your own. Something like the following:

我会使用 Java 5Executors而不是滚动你自己的。类似于以下内容:

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

回答by RalphChapin

Use the Executors, as recommended by the others. However, if you want the fun of doing it yourself, try something like this. (Take care. I wrote it in Notepad and there's some Exceptions you'll need to catch even if I got everything else right. Notepad's poor at catching coding errors.) This is more a concept than an actual solution to anything, but the idea could be generally useful.

按照其他人的建议使用 Executors。但是,如果您想要自己动手做的乐趣,请尝试这样的操作。(小心。我是用记事本写的,即使我把其他一切都做对了,你也需要捕捉一些异常。记事本在捕捉编码错误方面很差。)这更像是一个概念,而不是任何实际解决方案,但这个想法可能普遍有用。

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

Elsewhere:

别处:

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

Also, note the clever use of ConcurrentLinkedQueue. You could use something else like ArrayList or LinkedList, but you'd need to synchronize them.

另外,请注意 ConcurrentLinkedQueue 的巧妙使用。您可以使用其他类似 ArrayList 或 LinkedList 的东西,但您需要同步它们。

回答by RalphChapin

Crate Logger.class:

板条箱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();
        }

    }
}

Then insert bellow code in your main class :

然后在你的主类中插入波纹管代码:

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

回答by ControlAltDel

see java.util.concurrent and especially Executors and ExecutorService

参见 java.util.concurrent 尤其是 Executors 和 ExecutorService