Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java设置来自ExecutorService的回调_Java_Multithreading_Callback_Threadpool_Executorservice - Fatal编程技术网

Java设置来自ExecutorService的回调

Java设置来自ExecutorService的回调,java,multithreading,callback,threadpool,executorservice,Java,Multithreading,Callback,Threadpool,Executorservice,我有一个fixedThreadPool,用于运行一组工作线程,以实现具有多个组件的任务的并行执行 当所有线程完成后,我使用一个方法(getResult)检索它们的结果(相当大),并将它们写入一个文件 最后,为了节省内存并能够看到中间结果,我希望每个线程在完成执行后将其结果写入文件,然后释放内存 通常,我会在run()方法的末尾添加相应的代码。但是,此类中的某些其他对象也调用这些线程,但不希望它们将结果写入文件,而是使用它们的结果执行其他计算,这些计算最终写入文件 因此,我想知道是否有可能在线程使

我有一个fixedThreadPool,用于运行一组工作线程,以实现具有多个组件的任务的并行执行

当所有线程完成后,我使用一个方法(getResult)检索它们的结果(相当大),并将它们写入一个文件

最后,为了节省内存并能够看到中间结果,我希望每个线程在完成执行后将其结果写入文件,然后释放内存

通常,我会在run()方法的末尾添加相应的代码。但是,此类中的某些其他对象也调用这些线程,但不希望它们将结果写入文件,而是使用它们的结果执行其他计算,这些计算最终写入文件

因此,我想知道是否有可能在线程使用ExecutorService完成的事件中附加一个回调函数。这样,我可以立即检索其结果并在该场景中释放内存,但在其他场景中使用这些线程时不会中断代码

这可能吗

因此,我想知道是否有可能在线程使用ExecutorService完成的事件中附加一个回调函数

不是直接的,不是,但是有几种方法可以做到这一点。想到的最简单的方法是将您的
Runnable
包装到另一个
Runnable
中,这样可以获得结果

所以你会做一些类似的事情:

threadPool.submit(new ResultPrinter(myRunnable));
...

private static class ResultPrinter implements Runnable {
    private final MyRunnable myRunnable;
    public ResultPrinter(MyRunnable myRunnable) {
        this.myRunnable = myRunnable;
    }
    public void run() {
        myRunnable.run();
        Results results = myRunnable.getResults();
        // print results;
    }
}
返回,帮助您检索结果,
ExecutorService#get
方法将阻止执行,直到计算未完成。范例-

ExecutorService executor = Executors.newFixedThreadPool(10);
Future<Long> future = executor.submit(new Callable<Long>(){
       @Override
       public Long call() throws Exception {
           long sum = 0;
           for (long i = 0; i <= 10000000l; i++) {
               sum += i;
           }
           return sum;
       }
});
Long result = future.get();
System.out.println(result);
ExecutorService executor=Executors.newFixedThreadPool(10);
Future=executor.submit(new Callable()){
@凌驾
public Long call()引发异常{
长和=0;

对于(长i=0;i如果使用Google Guava是一个选项,您可以通过以下方式使用该界面:

  • 通过
    MoreExecutors.ListingDecorator(existingExecutorService)
    ExecutorService转换为
  • ListeningExecutorService
    submit(Callable)
    方法已缩小范围,返回一个
    ListenableFuture
    ,它是
    Future
    的子接口
  • ListenableFuture
    有一个
    addListener()
    方法,因此您可以注册一个回调,以便在将来完成时运行

  • 您可以使用
    CompletableFuture
    在Java 8+中为线程返回添加回调,如下所示,
    t
    是长期运行计算的结果

    CompletableFuture.supplyAsync(() -> {
        T t = new T();
        // do something
        return t;
    }).thenApply(t -> {
        // process t
    });
    
    如果只想在Java 7中使用回调,可以执行以下操作:

    int x = 10;
    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(x);
    Future<T> result = fixedThreadPool.submit(() -> {
        // do calculation
        return T;
    });
    fixedThreadPool.submit(() -> {
        long minutesToWait = 5;
        T t = null;
        try {
            t = result.get(minutesToWait, TimeUnit.MINUTES);
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            LOGGER.error(e);
        }
        if (t != null) {
            // process t
        }
    });
    
    intx=10;
    ExecutorService fixedThreadPool=Executors.newFixedThreadPool(x);
    未来结果=fixedThreadPool.submit(()->{
    //计算
    返回T;
    });
    fixedThreadPool.submit(()->{
    long minutesowait=5;
    T=零;
    试一试{
    t=result.get(minutesToWait,TimeUnit.MINUTES);
    }捕获(InterruptedException | ExecutionException | TimeoutException e){
    错误(e);
    }
    如果(t!=null){
    //过程t
    }
    });
    
    Project Loom 有望为Java的并发设施带来新功能。基于早期访问Java 17的实验性构建。Loom团队正在征求反馈。有关更多信息,请参阅团队成员(如Ron Pressler或Alan Batman)的任何最新视频和文章。Loom已经进化,因此请研究最新的资源美国

    Project Loom的一个方便功能是使其成为be。这意味着我们可以使用try with resources语法自动关闭executor服务。
    try
    块末尾的控制块流,直到所有提交的任务完成/失败/取消。之后,executor服务将自动关闭。简化了我们的代码,并通过可视化代码结构使我们等待任务完成的意图显而易见

    ProjectLowe的另一个导入功能是虚拟线程(又称虚拟线程)。虚拟线程在内存和CPU方面都是轻量级的

    • 关于内存,每个虚拟线程都会得到一个堆栈,该堆栈会根据需要增减
    • 关于CPU,许多虚拟线程中的每一个都位于多个平台/内核线程中的任何一个之上。这使得阻塞非常便宜。当一个虚拟线程阻塞时,它被“停驻”(搁置),以便另一个虚拟线程可以继续在“真正的”平台/内核线程上执行
    轻量级意味着我们一次可以有很多虚拟线程,甚至数百万个

    ➥ 您的问题的挑战是,当提交的任务准备返回其结果时,立即做出反应,而不必等待所有其他任务完成。使用Project Loom技术,这要简单得多

    只需在另一个线程的每个
    Future
    上调用
    get
    因为我们有几乎无穷无尽的线程,而且阻塞非常便宜,所以我们可以提交一个任务,该任务只需调用,等待我们提交给执行器服务的每个线程返回的结果。对
    get
    的调用会阻塞,直到它来自的
    Callable
    完成其工作并返回结果

    通常,我们希望避免将
    Future 35; get
    调用分配给常规后台线程。该线程将停止所有进一步的工作,直到阻塞的
    get
    方法返回。但对于Project Lowe,会检测到该阻塞调用,并且其线程处于“停驻”状态,所以其他线程可能会继续。当被阻止的调用最终返回时,Loom也会检测到,这导致不再被阻止的任务的虚拟线程很快被安排在“真实”线程上进一步执行。所有这些停止和重新安排都会快速自动地进行,不会产生任何效果