【问题标题】:Java Completable future thread are alive after method executeJava Completable future 线程在方法执行后仍然存在
【发布时间】:2022-01-02 18:47:23
【问题描述】:

我编写了一个小程序来检查 Completable Future 的行为。我没有覆盖公共池。

我没有找到任何关闭方法,当我最后打印活动线程数时,我发现我的线程处于活动状态。

我的问题是他们什么时候结束,如果我在生活应用程序中使用它? 如果我在流量很大的公共 Api 中使用它,它们会创建很多线程吗?

我的示例代码

`

package rar;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

public class Rar {
    public static void main(String[] args) {
        Rar r = new Rar();
        
        
          Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
          System.out.println(threadSet); r.dfo(); threadSet =
          Thread.getAllStackTraces().keySet(); System.out.println("uyuuuu"+threadSet);
         
    }

    private static void doTask3() {
        for(int i=0; i<5;i++) {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.print(3);
        }

    }

    public  void dfo() {
         System.out.println("In main");      
         ExecutorService executor = Executors.newFixedThreadPool(3);     
         CompletableFuture<Void> thenCompose =CompletableFuture.allOf(
                 CompletableFuture.runAsync(() -> doTask1()),
                 CompletableFuture.runAsync(() -> doTask2(2)),
                 CompletableFuture.runAsync(() -> doTask3()));
                
        
         //executor.shutdown();    
         try {
             Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
             System.out.println(threadSet);

            thenCompose.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
         System.out.println("Exiting main");
         Set<Thread> threadSeWt = Thread.getAllStackTraces().keySet();
         System.out.println(threadSeWt);
    }
    private  void doTask2(int num) {
        for(int i=0; i<5;i++) {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.print("4");
        }

    }

    private  int doTask1() {
        for(int i=0; i<5;i++) {
            try {
                Thread.sleep(5001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.print(1);
        }
        return 5;

    }
}

`

样本输出:

 [Thread[Finalizer,8,system], Thread[Attach Listener,5,system], Thread[Signal Dispatcher,9,system], Thread[Reference Handler,10,system], Thread[main,5,main]]
In main
[Thread[Finalizer,8,system], Thread[ForkJoinPool.commonPool-worker-1,5,main], Thread[main,5,main], Thread[ForkJoinPool.commonPool-worker-2,5,main], Thread[Attach Listener,5,system], Thread[ForkJoinPool.commonPool-worker-3,5,main], Thread[Signal Dispatcher,9,system], Thread[Reference Handler,10,system]]
431413431431431Exiting main
[Thread[Finalizer,8,system], Thread[ForkJoinPool.commonPool-worker-1,5,main], Thread[main,5,main], Thread[ForkJoinPool.commonPool-worker-2,5,main], Thread[Attach Listener,5,system], Thread[ForkJoinPool.commonPool-worker-3,5,main], Thread[Signal Dispatcher,9,system], Thread[Reference Handler,10,system]]
uyuuuu[Thread[Finalizer,8,system], Thread[ForkJoinPool.commonPool-worker-1,5,main], Thread[main,5,main], Thread[ForkJoinPool.commonPool-worker-2,5,main], Thread[Attach Listener,5,system], Thread[ForkJoinPool.commonPool-worker-3,5,main], Thread[Signal Dispatcher,9,system], Thread[Reference Handler,10,system]]

【问题讨论】:

  • 这就是 pool 的意义所在,让它们保持活力和可重复使用。

标签: java java-8 completable-future forkjoinpool


【解决方案1】:

你的dfo()方法中的执行器没有被使用。

当您使用runAsync() 方法时,它在公共池上运行。这就是您在调试消息中看到ForkJoinPool 的原因。

默认情况下,该池的大小受“CPU 核心数 - 1”的限制。

尝试运行 20 个任务,您会发现线程数一旦达到最大值就会停止增长。

您不需要停止 ForkJoinPool 的线程。来自documentation

它的线程在不使用期间会慢慢回收

【讨论】:

  • 感谢@Alexey,我没有故意使用 Executor 来检查 Fork 加入池的行为。我想知道为什么我的线程仍然显示活跃,我应该怎么做才能关闭它们?如果我再次或三次回忆方法 dfo() 怎么办,然后他们创建新线程或重用旧线程?
  • 您不需要关闭它们。您可以多次调用dfo() 方法,您会看到线程数停止增长,因为已达到池的最大大小。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 2019-04-22
  • 2012-05-07
  • 1970-01-01
相关资源
最近更新 更多