【问题标题】:Java FixedThreadPool with resources per thread?每个线程都有资源的Java FixedThreadPool?
【发布时间】:2020-06-05 17:40:28
【问题描述】:

这是我当前工作代码的伪代码版本:

public class DataTransformer {
    private final boolean async = true;
    private final ExecutorService executorService = Executors.newSingleThreadExecutor();

    public void modifyAsync(Data data) {
        if (async) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    modify(data);
                }
            });
        } else {
            modify(data);
        }
    }

    // This should actually be a variable inside modify(byte[] data)
    // But I reuse it to avoid reallocation
    // This is no problem in this case
    // Because whether or not async is true, only one thread is used
    private final byte[] temp = new byte[1024];

    private void modify(Data data) {
        // Do work using temp
        data.setReady(true); // Sets a volatile flag
    }
}

请阅读 cmets。但现在我想使用Executors.newFixedThreadPool(10) 而不是Executors.newSingleThreadExecutor()。在我的情况下,这很容易通过将字段temp 移动到modify(Data data) 中来实现,这样每次执行都有自己的temp 数组。但这不是我想做的,因为我想尽可能重用数组。相反,我希望 10 个线程中的每一个线程都有一个 temp 数组。实现这一目标的最佳方法是什么?

【问题讨论】:

  • 您可以使用ThreadLocal 或其他一些池化机制。
  • Re, "...但我重复使用它以避免重新分配。"在重新使用temp 数组而不是为每个任务分配一个新数组时,您是否测量任何性能改进? Java 程序创建大量短期对象是正常的,堆和垃圾收集器经过优化以有效处理这种情况。
  • 在这种特殊情况下,如果不进行池化,它可能会更快。但是我也很好奇这个基本怎么实现。
  • @stonar96,所以你想在线程之间共享数据吗?
  • 你可以将 temp 声明为 static 或者如果你想使用不同的值然后使用 threadlocal

标签: java multithreading resources thread-safety executorservice


【解决方案1】:

由于static 变量在所有线程之间共享,因此您可以声明为静态。但是如果你想使用不同的值,那么要么使用 Threadlocal 要么使用不同的对象。

使用 ThreadLocal 你可以做到:

  ThreadLocal<byte[]> value = ThreadLocal.withInitial(() -> new byte[1024]);

你也可以像这样使用对象:

public class Test {

public static void main(String[] args) {
    try {
        Test test = new Test();
        test.test();
    } catch (Exception e) {
        e.printStackTrace();
    }

}
class Control {
    public volatile byte[] temp = "Hello World".getBytes();
}
final Control control = new Control();

class T1 implements Runnable {
    @Override
    public void run() {
        String a = Arrays.toString(control.temp);
        System.out.println(a);
    }
}
class T2 implements Runnable {
    @Override
    public void run() {
        String a = Arrays.toString(control.temp);
        System.out.println(a);
        }
    }
private void test() {
    T1 t1 = new T1();
    T2 t2 = new T2();

    new Thread(t1).start();
    new Thread(t2).start();
}
}  

【讨论】:

  • 虽然ThreadLocal 确实解决了我的问题,但我认为您并没有完全理解我在问什么。我不会尝试与线程之间的临时数组或modify(Data data) 的调用共享任何状态。因此,单独static 不是解决方案。在初始示例中,将其设为静态甚至会导致不同 SingleThreadExecutors 之间的并发问题。但是制作static ThreadLocal 很好。您的第二个代码示例仅显示了如何在线程之间共享数据,甚至不包括对 temp 的写入。这不是我要问的。
  • 我的问题是关于如何重用分配的数组而不是它的内容。上一次执行的数组的全部内容在modify(Data data) 中被覆盖。所以如果你的回答只是/*static optional*/ ThreadLocal&lt;byte[]&gt; value = ThreadLocal.withInitial(() -&gt; new byte[1024]);,我可以接受。
猜你喜欢
  • 2010-09-24
  • 2021-11-26
  • 1970-01-01
  • 1970-01-01
  • 2019-06-03
  • 1970-01-01
  • 2021-05-31
  • 2012-04-18
  • 1970-01-01
相关资源
最近更新 更多