Java将对象与Executor中的每个线程关联 [英] Java associate object with each thread in Executor

查看:63
本文介绍了Java将对象与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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆