Java-FixedThreadPool具有已知的池大小但未知的工作者

时间:2012-10-28 15:48:53

标签: java multithreading threadpool executor

所以我想我有点理解固定线程池是如何工作的(使用Java内置的Executor.fixedThreadPool),但从我所看到的,通常你需要完成一定数量的工作,你知道有多少工作时间你启动程序。例如

int numWorkers = Integer.parseInt(args[0]);
int threadPoolSize = Integer.parseInt(args[1]);
ExecutorService tpes =
    Executors.newFixedThreadPool(threadPoolSize);
WorkerThread[] workers = new WorkerThread[numWorkers];
for (int i = 0; i < numWorkers; i++) {
    workers[i] = new WorkerThread(i);
    tpes.execute(workers[i]);
}

每个workerThread都非常简单,那部分是任意的。我想知道的是,如果你有一个固定的游泳池大小(比如最多8个),但你不知道在运行时间之前完成任务需要多少工人。

具体的例子是:如果我的游泳池大小为8,我正在从标准输入中读取。在我阅读时,我将输入分成一组大小的块。这些块中的每一个都被赋予一个线程(以及一些其他信息),以便它们可以压缩它。因此,我不知道我需要创建多少线程,因为我需要继续前进,直到我到达输入结束。我还必须以某种方式确保数据保持相同的顺序。如果线程2在线程1之前完成并且只是提交它的工作,那么我的数据就会出现故障!

在这种情况下,线程池会是错误的方法吗?看起来它很棒(因为我一次不能使用8个以上的线程)。

基本上,我想做这样的事情:

ExecutorService tpes = Executors.newFixedThreadPool(threadPoolSize);
BufferedInputStream inBytes = new BufferedInputStream(System.in);
byte[] buff = new byte[BLOCK_SIZE];
byte[] dict = new byte[DICT_SIZE];
WorkerThread worker;
int bytesRead = 0;

while((bytesRead = inBytes.read(buff)) != -1) {
   System.arraycopy(buff, BLOCK_SIZE-DICT_SIZE, dict, 0, DICT_SIZE);
   worker = new WorkerThread(buff, dict)   
   tpes.execute(worker);
}

这不是正常工作的代码,我知道,但我只是想说明我想要的东西。

我遗漏了一些,但看看buff和dict如何改变值,我不知道输入有多长。我不认为我实际上不能这样想,因为第一次通话后工人已经存在!我不能简单地说worker = new WorkerThread一堆时间,因为它不是已经指向现有线程(是的,一个可能已经死的线程),显然在这个实现中,如果它确实有效,我就不会运行在平行下。但我的观点是,我想继续创建线程,直到我达到最大池大小,等到线程完成,然后继续创建线程,直到我到达输入结束。

我还需要按顺序保存东西,这是非常讨厌的部分。

2 个答案:

答案 0 :(得分:1)

正如@ignis指出的那样,并行执行可能不是您情况的最佳答案。 但是,为了回答更一般的问题,除了FixedThreadPool之外还有其他一些Executor实现需要考虑,其中一些可能具有您想要的特性。

就保持秩序而言,通常你会向执行者提交任务,并且对于每次提交,你都会得到一个Future(这是一个承诺在任务完成后会给你一个结果的对象)。因此,您可以按照提交任务的顺序跟踪期货,然后在完成所有任务后,按顺序调用每个Future的get(),以获得结果。

答案 1 :(得分:1)

您的解决方案完全没问题(唯一的一点是,如果WorkerThread的工作量非常小,可能不需要并行性。)

使用线程池,提交的任务数量不相关。可能少于或多于池中的线程数,线程池负责处理。

然而,这很重要:您依赖于WorkerThread s的某种结果顺序,但在使用并行性时,此订单无法保证!无论您是使用线程池,还是使用多少工作线程等,您的结果总是可能以任意顺序完成!

为了保持秩序正确,请为每个WorkerThread提供其构造函数中当前项目的编号,并让它们在完成后按正确的顺序放置:

int noOfWorkItem = 0;
while((bytesRead = inBytes.read(buff)) != -1) {
   System.arraycopy(buff, BLOCK_SIZE-DICT_SIZE, dict, 0, DICT_SIZE);
   worker = new WorkerThread(buff, dict, noOfWorkItem++)   
   tpes.execute(worker);
}