Java将对象与Executor中的每个线程关联 [英] Java associate object with each thread in Executor
问题描述
我有一堆要通过线程池执行的可运行对象.但是,每个可运行对象也会将一些结果写入某个文件.因此,现在,可运行对象的界面很简单:
I have a bunch of runnables that I want to execute via a thread pool. However, each runnable also writes some result to some file. So right now, the runnable's interface is simple:
class MyRunnable implements Runnable {
...
MyRunnable(BufferedWriter writer, Task t) {
this.writer = writer;
this.task = t;
}
public void run() {
...
this.writer.write(SOME_DATA);
}
}
但是,我想要的是将一个BufferedWriter(换句话说,一个输出文件)与Executor池中的每个线程相关联.但是,我使用 ExecutorService
调用 .execute
函数,如下所示:
However, what I want is to associate one BufferedWriter (in other words, one output file) with each of the thread in the Executor pool. However, I'm calling the .execute
function using ExecutorService
like the following:
BufferedWriter[] writers = initialize to 20 BufferedWriters;
ExecutorService executor = Executors.newFixedThreadPool(20);
for (Task t : tasks) {
MyRunnable runnable = new MyRunnable(WHAT SHOULD GO HERE?, t)
executor.execute(runnable);
}
我不知道执行程序将分配哪个线程来运行给定任务,所以我不知道我应该向可运行对象提供哪个BufferedWriter.如何确保ExecutorService管理的每个线程都与一个对象(在本例中为BufferedWriter)相关联?
I don't know which thread the executor will assign to run a given task, so I don't know which BufferedWriter I should provide to the runnable. How can I ensure that each thread managed by the ExecutorService is associated with one object (in this case a BufferedWriter)?
推荐答案
...我想要的是将一个BufferedWriter(换句话说,一个输出文件)与Executor池中的每个线程相关联...
... I want is to associate one BufferedWriter (in other words, one output file) with each of the thread in the Executor pool...
@djechlin关于 ThreadLocal
的答案很好,但是问题在于您无法访问 BufferedWriter
到 close()
在线程完成最后一个任务时结束.
@djechlin's answer about ThreadLocal
is good but the problem with it is that you can't get access to the BufferedWriter
to close()
them when the threads finish running the last task.
可以在这里看到另一个答案:
An alternative answer can be seen here:
我建议在其中创建您自己的任务的 BlockingQueue
并为每个线程派发一个任务,并让这些线程从您的队列中获取任务.因此,线程运行方法将类似于:
In it I recommend creating your own BlockingQueue
of tasks and forking one task per thread and having those threads get the tasks from your queue. So the thread run method would be something like:
private final BlockingQueue<MyRunnable> queue = new ArrayBlockingQueue<>();
// if you want to shutdown your threads with a boolean
private volatile boolean shutdown;
...
// threads running in the `ExecutorService` will be doing this run() method
public void run() {
// this allows them to maintain state, in this case your writer
BufferedWriter writer = ...;
while (!shutdown && !Thread.currentThread.isInterrupted()) {
// they get their tasks from your own queue
MyRunnable runnable = queue.take();
// if you are using a poison pill but you'll have to add X of them
if (runnable == STOP_OBJECT) {
break;
}
runnable.run();
}
writer.close();
}
在完成线程处理后,在这里告诉它们有些棘手.您可以在队列中添加一个毒丸"对象,但是必须在队列中添加与正在运行的线程数量相同的对象.
Telling the threads when they are done is a little tricky here. You could add a "poison pill" object to the queue but you would have to add the same number of objects to the queue as there are threads running.
这篇关于Java将对象与Executor中的每个线程关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!