Java将对象与Executor中的每个线程相关联
我有一堆要通过线程池执行的可运行程序。但是,每个runnable还将一些结果写入某个文件。现在,runnable的接口很简单:Java将对象与Executor中的每个线程相关联,java,multithreading,executorservice,Java,Multithreading,Executorservice,我有一堆要通过线程池执行的可运行程序。但是,每个runnable还将一些结果写入某个文件。现在,runnable的接口很简单: class MyRunnable implements Runnable { ... MyRunnable(BufferedWriter writer, Task t) { this.writer = writer; this.task = t; } public void run() { ..
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
函数,如下所示:
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);
}
我不知道执行器将分配哪个线程来运行给定的任务,所以我不知道应该向runnable提供哪个BufferedWriter。如何确保ExecutorService管理的每个线程都与一个对象(在本例中为BufferedWriter)关联?为此有一个类
e、 g
ThreadLocal t=new ThreadLocal(){
@重写受保护的类型initialValue(){
返回新类型(Thread.currentThread.getName());
}
这将在每次新线程尝试访问t
时延迟初始化类型
我上一次使用这个类仅仅是在一个类中计算出某台机器的最佳运行线程数。(答案通常是“内核数”,但我想确保虚拟内核驱动这个数,而不是物理内核)。因此,我编写了一个任务,其中每个线程只发送一个AtomicInteger
计数器。但是所有线程都在为一个计数器而斗争,这会在处理线程争用时产生大量开销,因此我创建了一个threadlocal计数器,这样线程就可以发送自己的计数器,而不会受到其他线程的干扰
它的用例有些模糊,因为大多数好的多线程设计都会避免这种情况,但当然也会有这样的情况出现。有一个类为此而命名
e、 g
ThreadLocal t=new ThreadLocal(){
@重写受保护的类型initialValue(){
返回新类型(Thread.currentThread.getName());
}
这将在每次新线程尝试访问t
时延迟初始化类型
我上一次使用这个类仅仅是在一个类中计算出某台机器的最佳运行线程数。(答案通常是“内核数”,但我想确保虚拟内核驱动这个数,而不是物理内核)。因此,我编写了一个任务,其中每个线程只发送一个AtomicInteger
计数器。但是所有线程都在为一个计数器而斗争,这会在处理线程争用时产生大量开销,因此我创建了一个threadlocal计数器,这样线程就可以发送自己的计数器,而不会受到其他线程的干扰
它的使用案例有些模糊,因为大多数好的多线程设计都避免了这种情况,但当然也有这样的时候
…我想要的是将一个BufferedWriter(换句话说,一个输出文件)与执行器池中的每个线程关联
@djechlin关于ThreadLocal
的回答很好,但问题是,当线程完成运行最后一个任务时,您无法访问BufferedWriter
以close()
这里可以看到另一个答案:
在本文中,我建议您创建自己的任务阻塞队列
,并为每个线程分叉一个任务,让这些线程从您的队列中获取任务。因此,线程运行方法类似于:
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();
}
private final BlockingQueue=new ArrayBlockingQueue();
//如果要使用布尔值关闭线程
私有易失性布尔关闭;
...
//在“ExecutorService”中运行的线程将执行此run()方法
公开募捐{
//这允许它们维护状态,在本例中是您的编写器
BufferedWriter=。。。;
而(!shutdown&!Thread.currentThread.isInterrupted()){
//他们从您自己的队列中获取任务
MyRunnable=queue.take();
//如果你使用的是毒药丸,但你必须添加X颗
if(runnable==停止对象){
打破
}
runnable.run();
}
writer.close();
}
在这里告诉线程何时完成有点棘手。你可以向队列中添加一个“毒药丸”对象,但你必须向队列中添加与正在运行的线程数量相同的对象
…我想要的是将一个BufferedWriter(换句话说,一个输出文件)与执行器池中的每个线程关联
@djechlin关于ThreadLocal
的回答很好,但问题是,当线程完成运行最后一个任务时,您无法访问BufferedWriter
以close()
这里可以看到另一个答案:
在本文中,我建议您创建自己的任务阻塞队列
,并为每个线程分叉一个任务,让这些线程从您的队列中获取任务。因此,线程运行方法类似于:
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();
}
private final BlockingQueue=new ArrayBlockingQueue();
//如果要使用布尔值关闭线程
私有易失性布尔关闭;
...
//在“ExecutorService”中运行的线程将执行此run()方法
公开募捐{
//这允许它们维护状态,在本例中是您的编写器
BufferedWriter=。。。;
而(!shutdown&!Thread.currentThread.isInterrupted()){
//他们从您自己的队列中获取任务
MyRunnable=queue.take();
//如果你使用的是毒药丸,但你必须添加X颗
if(runnable==停止对象){
打破
}
runnable.run();
}
writer.close();
}
告诉线程何时完成有点棘手。你可以在队列中添加一个“毒丸”对象,但你必须添加相同数量的ob