【问题标题】:ExecutorService, Future, Threads appears Actives when all Runnables must be finishedExecutorService、Future、Threads 在所有 Runnables 必须完成时出现 Actives
【发布时间】:2019-09-23 23:51:40
【问题描述】:

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

我想知道为什么 Runnable/Threads 似乎正在运行,而我的应用程序仍在运行,而我希望它们都必须完成。

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

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 中运行应用程序时,保持“运行”状态,但所有 Runnable 都必须完成!

为什么线程似乎处于活动状态? 这是什么意思?

如何完成?

【问题讨论】:

    标签: java multithreading executorservice runnable


    【解决方案1】:

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

    你可以通过调用方法来做到这一点

     `shutdown() or shutdownNow()`
    

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

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

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

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

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

    【讨论】:

    • 稍后我发布我的问题,我得到了相同结果但没有解释的答案。谢谢你,我明白了原因。
    猜你喜欢
    • 2018-09-22
    • 1970-01-01
    • 2016-12-26
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    • 1970-01-01
    • 1970-01-01
    • 2015-02-14
    相关资源
    最近更新 更多