如何将ExecuteService与包含AutoCloseable资源的自定义线程一起使用

时间:2019-05-13 20:36:03

标签: java multithreading resources threadpool executor

我在这里简化了我要解决的问题。我介绍的课程摘要:

  • 处理器:是一个非线程安全的类,可以创建时不带任何参数,并且在使用完该类后需要将其关闭。创建此类的实例确实非常昂贵,因此只能创建一个(每个线程)。它提供了执行某些操作的方法。
  • ResultProvider:是线程安全的类,用于管理需要处理处理器的请求。

当前实现类似于以下内容:

class Processor implements AutoCloseable { (...) }

class ResultProvider implements AutoCloseable {

    private final Processor processor;

    public ResultProvider() {
        this.processor = Processor.createNewProcessor();
    }

    /*
     * The 'request' doesn't turn a Procesoor into a T, it rather uses a Processor
     * as a resource, to be able to compute a T
     */
    public synchronized <T> T handle(Function<Processor, T> request) {
        request.apply(processor);
    }

    public synchronized void close() {
        processor.close();
    }
}

现在,我想使ResultProvider能够使用多个CPU内核。理想情况下,我希望能够使用ExecutorService来执行此操作。 请注意,每个线程在启动时都需要实例化其自己的处理器,并且在委派该线程时需要将其关闭.close()。 “ ExecutorService”应该使用ThreadFactory来创建一个自定义Thread子类,以实例化并关闭内部Processor。

我想我想要的是这样的东西:

class ResultProvider implements AutoCloseable {

    private static class ProcessorThread extends Thread {
        final private Processor processor = Processor.createNewProcessor();

        public void run() {
            try {
                super.run();
            } finally {
                processor.close();
            }
        }
    }

    private final ExecutorService executor;
    /*
     * Not sure how to create one that uses my ProcessorThread and is able
     * to be submitted Function<Processor, T> to get T...
     */

    public ResultProvider() {
        // ...
    }

    /*
     * The 'request' doesn't turn a Procesoor into a T, it rather uses a Processor
     * as a resource, to be able to compute a T
     */
    public <T> T handle(Function<Processor, T> request) {
        return executor.submit?(request).get();
    }

    public synchronized void close() {
        executor.shutdown();
        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
    }
}

现在,可行吗?我不知道如何使用尽可能多的Java并发类来实现它。有什么建议吗?

1 个答案:

答案 0 :(得分:2)

您不需要任何自定义线程。您需要做的就是创建并提交一个Callable来创建处理器,调用函数并关闭处理器:

public <T> T handle(Function<Processor, T> request) {
    Callable<T> callable = () -> {
        try(Processor processor = Processor.createNewProcessor()) {
            request.apply(processor);
        } 
    }
    return executor.submit(callable).get();
}

请注意,同步是没有用的:该方法不使用任何可变状态。

如果您确实希望每个线程有一个处理器,而不是每个可调用的处理器,那么您可以使用您的问题所示的自定义工厂,除非处理器将从ThreadLocal获得(在自定义线程和任务)。