如何关闭并行流中使用的本地autocloseable线程?

hey*_*you 3 java java-8 java-stream

我有一个ThreadLocal变量.我想像这样使用它:

ThreadLocal<AutoCloseable> threadLocal = new ThreadLocal<AutoCloseable>(); // pseudocode
ForkJoinPool fj = new ForkJoinPool(nThreads);
fj.submit(
    () -> myStream.parallel().forEach(e -> {
        /*I want to use the thread local autocloseable here, 
          but how do I close it when this parallel processing is done?*/
    })
);
Run Code Online (Sandbox Code Playgroud)

Pet*_*rey 7

ThreadLocal在使用它们的线程死后关闭.如果你想控制它,你需要使用地图.

// do our own thread local resources which close when we want.
Map<Thread, Resource> threadLocalMap = new ConcurrentHashMap<>();

fj.submit(
() -> myStream.parallel().forEach(e -> {
     Resource r = threadLocalMap.computeIfAbsent(Thread.currentThread(), t -> new Resource();
    // use the thread local autocloseable here, 
})

// later once all the tasks have finished.
// close all the thread local resources when the parallel processing is done
threadLocalMap.values().forEach(Utils::closeQuietly);
Run Code Online (Sandbox Code Playgroud)

有一种方法可以在不抛出异常的情况下关闭资源.Chronicle有一个,但许多其他库也是如此.

public static void closeQuietly(Closeable c) {
    if (c != null) {
       try {
           c.close();
       } catch (IOException ioe) {
           // ignore or trace log it
       }
    }
}
Run Code Online (Sandbox Code Playgroud)

很可能你有一个方法在你的项目中做到这一点 https://www.google.co.uk/search?q=public+static+void+closequietly+Closeable

  • 你的意思是`threadLocal.values().forEach(Utils :: closeQuietly);`顺便说一句,你可以将这种方法与`ThreadLocal`结合起来,以减少`ConcurrentHashMap`查找的次数.使用`Map <Thread,Resource>初始化threadLocal = new ConcurrentHashMap <>(); ThreadLocal <Resource> resources = ThreadLocal.withInitial(() - > threadLocal.computeIfAbsent(Thread.currentThread(),t - > new Resource()));`.然后,在流操作中,您可以使用简单而有效的`Resource r = resources.get();`.清理保持不变. (3认同)
  • "ThreadLocals"的值可能会在某个时间收集垃圾.但这并不意味着资源被关闭,因为这需要特定的资源类实现终结器或类似的进行清理(我们都知道,强烈建议不要依赖终结器).线程死后可能会有一段不可预测的长时间,直到垃圾收集器实际收集它为止.更糟糕的是,并行流使用线程池,因此甚至没有保证工作线程在操作后死亡. (2认同)