【问题标题】:Executor Thread still shown in CPU执行器线程仍显示在 CPU 中
【发布时间】:2020-03-22 23:43:37
【问题描述】:

我正在解决一个问题,我将任务发布到每个实例的执行程序中,一旦它的工作结束,实例就会从内存中清除,我在一系列强制垃圾收集后进行了内存转储,但可以找不到任何持有执行人的人的实例。但是我仍然可以看到 executor 创建的线程仍然存在于 CPU 中,但处于睡眠状态,并且在应用程序生命周期内一直存在,我不知道如何清除它或将其从 CPU 中删除。

这种情况并非每次都发生,有时它会从内存中清除,有时不会。但主要是它正在被清除。但如果这种情况继续发生,那么设备最终可能会导致 OutOfMemory(OOMs) 崩溃,因为它无法创建更多线程。

我尝试在执行程序上调用 shutdown() 方法,但似乎也不起作用。

class MyThread extends Thread {
    MyThread(Runnable r, String name) {
        super(r, name);
    }
}
class YourThreadFactory implements ThreadFactory {
    int thread = -1;

    YourThreadFactory() {
    }

    @Override
    public Thread newThread(@NonNull Runnable r) {
        thread = SomeStaticClass.thread++;
        return new MyThread(r, "MyThread " + thread);
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize(); 
        Log.d("ThreadFactory",  Thread.currentThread().getName()  + " " + " Executor removed " + thread);

    }
}
ExecutorService mSingleThreadExecutor = Executors.newSingleThreadExecutor(new YourThreadFactory());

【问题讨论】:

    标签: java android multithreading executorservice threadpoolexecutor


    【解决方案1】:

    恕我直言,你做错了:

    1. 永远不要使用 finalize()
    2. 您不应该在应用程序中创建更多 ExecutorService 实例,最佳做法是在整个应用程序中只创建一个 ExecutorService 实例
    3. ExecutorService 的shutdown() 方法有效,它只是等到所有提交的任务都被终止:https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html

    【讨论】:

    • 我没有使用 finalize(),它只是为了知道它是否被调用。如果它被调用,那么我正在进行分析以检查该线程是否仍然存在于 CPU 中。
    • 好的,公平点。顺便说一句,请查看这篇文章,恕我直言,它会回答您关于执行者的所有问题:baeldung.com/java-executor-service-tutorial
    【解决方案2】:

    您可能应该将此线程绑定到 android 应用程序的范围(假设这是与 android 相关的,因为您有一个 android 标签)。您可以使用interrupt,然后将线程实例设置为null。

    对于自定义线程,也许您可​​以:

    public void stopThread(){
      if(thread !=null){
          thread.interrupt();
          thread = null;
      }
    }
    

    理想情况下,将其绑定到 onDestroy

    希望对你有帮助!!

    【讨论】:

      【解决方案3】:

      您已经定义了一个Executors.newSingleThreadExecutor(),它最多只会创建一个线程。如果您的应用程序达到了最大线程的内核限制,那么某些东西正在创建线程,而不是这个只有一个线程的ExecutorService 对象。

      请注意,您应该为您的任务创建一个 ExecutorService 的单个实例,并使用 submit() 将任务排入队列。 ExecutorService 不是 Thread 包装器。 Executor 用于通过定义线程池来定义应用程序中的并发级别。

      如果您无法使用shutdown() 关闭ExecutorService,则表示正在处理任务。您可以通过调用 shutdownNow() 来终止,但您的任务会被中断。

      【讨论】:

      • 在创建每个实例的用例中,我想同时执行的任务很少,但没有两个实例相关,它们可以单独运行。这就是我在每次创建实例时都创建实例的原因。
      • 在清除我的实例时,我正在调用执行器的关闭,并且它也被调用,但我仍然可以在 CPU 中看到该线程
      • 恕我直言,这更像是ComplatableFuture 的用例,而不是单独的ExecutorService
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-11
      • 2011-07-21
      • 2014-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多