所以在Java并发中,有一个任务的概念,它实际上是任何实现Runnable
或Callable
(更具体地说,是被覆盖的run()
或该接口的call()
方法。)
我很难理解两者之间的关系:
Runnable
/ Callable
);和ExecutorService
;和ExecutorService
我相信这种关系是以下内容:
ExecutorService
和工作结构ExecutorService
(例如,作为ScheduledThreadPool
)(例如,ArrayBlockingQueue
)(如果是,如何?!?! )ExecutorService
,{{1}}然后使用其线程/池策略使用任务副本填充给定结构(ABQ或其他)首先,如果我偏离任何一个假设,请更正/澄清上述任何假设!
其次,如果任务只是在底层工作结构中反复复制 /复制(例如,列表的每个索引中的相同副本),那么你如何分解一个大的问题分解为较小(并发)的问题?换句话说,如果任务只执行步骤A-Z,并且你有一个包含1,000个这些任务的ABQ,那么每个线程也不会只执行A - Z吗? How do you say“一些线程应该在A - G上工作,而其他线程应该在H上工作,但其他线程应该工作在我 - Z”等等?
对于第二个,我可能需要一个代码示例来可视化它们如何结合在一起。提前谢谢。
答案 0 :(得分:2)
你最后的假设是不对的。 ExecutorService
不会提取任务的副本。该程序必须单独提供由ExecutorService
执行的所有任务。任务完成后,将执行队列中的下一个任务。
ExecutorService
是用于处理线程池的接口。您通常需要在池上执行多个任务,并且每个任务都在问题的不同部分上运行。作为开发人员,在将任务发送到ExecutorService
之前,必须指定每个任务在创建时应该处理的问题部分。应该将每个任务的结果(假设它们正在处理一个常见问题)添加到BlockingQueue
或其他并发集合中,其中另一个线程可以使用结果或等待所有任务完成。
以下是您可能想要阅读的有关如何使用ExecutorService
的文章:http://www.vogella.com/articles/JavaConcurrency/article.html#threadpools
更新:ExecutorService
的一个常见用途是实现生产者/消费者模式。这是一个我快速拼凑起来让你入门的例子 - 它仅用于演示目的,因为为简单起见省略了一些细节和关注点。线程池包含多个生产者线程和一个消费者线程。正在执行的工作是将数字从0 ... N中求和。每个生成器线程对较小的数字间隔求和,并将结果发布到BlockingQueue
。消费者线程处理添加到BlockingQueue
的每个结果。
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class NumberCounter {
private final ExecutorService pool = Executors.newFixedThreadPool(2);
private final BlockingQueue<Integer> queue = new ArrayBlockingQueue(100);
public void startCounter(int max, int workers) {
// Create multiple tasks to add numbers. Each task submits the result
// to the queue.
int increment = max / workers;
for (int worker = 0; worker < workers; worker++) {
Runnable task = createProducer(worker * increment, (worker + 1) * increment);
pool.execute(task);
}
// Create one more task that will consume the numbers, adding them up
// and printing the results.
pool.execute(new Runnable() {
@Override
public void run() {
int sum = 0;
while (true) {
try {
Integer result = queue.take();
sum += result;
System.out.println("New sum is " + sum);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
private Runnable createProducer(final int start, final int stop) {
return new Runnable() {
@Override
public void run() {
System.out.println("Worker started counting from " + start + " to " + stop);
int count = 0;
for (int i = start; i < stop; i++) {
count += i;
}
queue.add(count);
}
};
}
public static void main(String[] args) throws InterruptedException {
NumberCounter counter = new NumberCounter();
counter.startCounter(10000, 5);
}
}