所以我想我有点理解固定线程池是如何工作的(使用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一堆时间,因为它不是已经指向现有线程(是的,一个可能已经死的线程),显然在这个实现中,如果它确实有效,我就不会运行在平行下。但我的观点是,我想继续创建线程,直到我达到最大池大小,等到线程完成,然后继续创建线程,直到我到达输入结束。
我还需要按顺序保存东西,这是非常讨厌的部分。
答案 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);
}