ExecutorService、Future、Threads在所有Runnables必须完成时出现Actives

ExecutorService, Future, Threads appears Actives when all Runnables must be finished

我有一个复杂的程序,使用 运行nable、ExecutorService 和 Future。

我想知道为什么Runnable/Threads会出现运行ning,而我的申请还在运行ning,我希望他们必须完成。

完整代码您可以复制和粘贴,运行,您需要的都在这里。

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;

public class TestFutureExecutorService {

  public static void main(String... args) {

    List<Future<?>> futureList = new ArrayList<>();
    ExecutorService executorService = Executors.newCachedThreadPool();

    RunnableTest rt = new RunnableTest("rt", futureList, executorService);

    new Timer(false).schedule(new TimerTask() {
      @Override
      public void run() {
        rt.stop();
      }
    }, ThreadLocalRandom.current().nextLong(100L, 500L));

    System.out.println("Let's go to check the threads status.\n");
    for (int i = 0; i < futureList.size(); i++) {//Working!
      try {
        if (futureList.get(i) != null) {
          futureList.get(i).get();
        }
      } catch (InterruptedException e) {
        e.printStackTrace();
      } catch (ExecutionException e) {
        e.printStackTrace();
      }
    }
    System.out.println("Apparently everything is finished.\n");

    boolean allDone = true;
    for (int i = 0; i < futureList.size(); i++) {
      if (futureList.get(i) != null) {
        allDone &= futureList.get(i).isDone(); // check if future is done
      }

    }
    System.out.println("Is everything really finished?:" + allDone + ".\n");
    //executorService.shutdown();

    Thread thisThread = Thread.currentThread();
    thisThread.setName("Admin Thread");
    thisThread.setPriority(1);
    System.out.println("Thread = " + thisThread);

    int count = Thread.activeCount();
    System.out.println("currently active threads = " + count);

    Thread activeThreadsArray[] = new Thread[count];
    Thread.enumerate(activeThreadsArray);
    // prints active threads
    for (int i = 0; i < count; i++) {
      System.out.println(i + ": " + activeThreadsArray[i]);
    }

  }

  public static class RunnableTest implements Runnable {
    private final String name;
    private final List<Future<?>> futureList;
    private final ExecutorService executorService;
    private volatile boolean isRunning = false;

    public RunnableTest(String name, List<Future<?>> futureList, ExecutorService executorService) {
      this.name = name;
      this.futureList = futureList;
      this.executorService = executorService;
      this.futureList.add(this.executorService.submit(this));
    }

    @Override
    public void run() {
      Thread.currentThread().setName(Thread.currentThread().getName() + this.getClass().getSimpleName() + ":" + name);
      isRunning = true;
      while (isRunning) {
        try {
          Thread.sleep(50);
          new Processor(this.futureList, this.executorService);
        } catch (Exception ex) {
          Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
        }
      }
        System.out.println("Finishing:" + Thread.currentThread().getName());
    }

    public void stop() {
      isRunning = false;
    }

  }

  public static class Processor implements Runnable {

    private final List<Future<?>> futureList;
    private final ExecutorService executorService;

    public Processor(List<Future<?>> futureList, ExecutorService executorService) {
      this.futureList = futureList;
      this.executorService = executorService;
      this.futureList.add(this.executorService.submit(this));
    }

    @Override
    public void run() {
      String hour = new SimpleDateFormat("_yyyyMMdd-HHmmss.SSSS_").format(new Date());
      Thread.currentThread().setName(hour + this.getClass().getSimpleName());
        try {
          int timeSleeping = ThreadLocalRandom.current().nextInt(100, 300);
          Thread.sleep(timeSleeping);
        } catch (Exception ex) {
          Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
        }
        System.out.println("Finishing:" + Thread.currentThread().getName());
    }
  }

}

现在,输出....

Let's go to check the threads status.

Finishing:_20190923-203808.0435_Processor
Finishing:_20190923-203808.0437_Processor
Finishing:_20190923-203808.0489_Processor
Finishing:pool-1-thread-1->RunnableTest:rt
Finishing:_20190923-203808.0695_Processor
Finishing:_20190923-203808.0544_Processor
Finishing:_20190923-203808.0593_Processor
Finishing:_20190923-203808.0746_Processor
Finishing:_20190923-203808.0645_Processor
Apparently everything is finished.

Is everything really finished?:true.

Thread = Thread[Admin Thread,1,main]
currently active threads = 8
0: Thread[Admin Thread,1,main]
1: Thread[pool-1-thread-1->RunnableTest:rt,5,main]
2: Thread[Timer-0,5,main]
3: Thread[_20190923-203808.0593_Processor,5,main]
4: Thread[_20190923-203808.0695_Processor,5,main]
5: Thread[_20190923-203808.0746_Processor,5,main]
6: Thread[_20190923-203808.0544_Processor,5,main]
7: Thread[_20190923-203808.0645_Processor,5,main]

当我运行申请的时候,在我的IDE里,还留着一些东西"running",但是所有运行nable都必须完成!

为什么线程显示为活动状态? 这是什么意思?

如何全部完成?

您正在使用 ExecutorService。 ExecutorService 使线程保持活动状态,以便为下一个任务做好准备。您必须告诉 ExecutorService 您不再有任务,它可以丢弃线程。

您可以通过调用方法来完成此操作

 `shutdown() or shutdownNow()`

因此在完成检查后取消注释代码中的行:

 System.out.println("Is everything really finished?:" + allDone + ".\n");
    //executorService.shutdown();

您的应用程序仍然不会完成,因为您将计时器线程创建为非守护线程,这意味着如果您的应用程序中存在 运行 个非守护线程,JVM 将不会停止。

您可以像这样将计时器创建为守护线程:

new Timer(true).schedule(new TimerTask() {