首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >由executor框架管理的线程转储

由executor框架管理的线程转储
EN

Stack Overflow用户
提问于 2020-05-22 09:59:59
回答 1查看 537关注 0票数 1

我写了下面的程序。基本上,我使用executor framework来管理线程。我还使用了一个BlockingQueue,并故意将它保持为空,以便线程保持在等待状态。

以下是计划:

代码语言:javascript
运行
复制
package com.example.executors;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class ExecutorDemo {

    public static void main(String[] args) throws InterruptedException {

        ScheduledExecutorService scheduledThreadPool = null;
        BlockingQueue<Integer> bq = new LinkedBlockingQueue<>();

        scheduledThreadPool = Executors.newSingleThreadScheduledExecutor((Runnable run) -> {
            Thread t = Executors.defaultThreadFactory().newThread(run);
            t.setDaemon(true);
            t.setName("Worker-pool-" + Thread.currentThread().getName());
            t.setUncaughtExceptionHandler(
                    (thread, e) -> System.out.println("thread is --> " + thread + "exception is --> " + e));
            return t;
        });

        ScheduledFuture<?> f = scheduledThreadPool.scheduleAtFixedRate(() -> {
            System.out.println("Inside thread.. working");
            try {
                bq.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }, 2000, 30000, TimeUnit.MILLISECONDS);

        System.out.println("f.isDone() ---> " + f.isDone());
        Thread.sleep(100000000000L);
    }
}

程序运行后,由于main thread (),TIMED_WAITING保持在TIMED_WAITING状态。在由executor管理的线程中,我让它读取一个空的阻塞队列,并且这个线程永远保持在WAITING状态。我想看看thread dump在这个场景中是怎样的。我在下面捕捉到了这一点:

代码语言:javascript
运行
复制
"Worker-pool-main" #10 daemon prio=5 os_prio=31 tid=0x00007f7ef393d800 nid=0x5503 waiting on condition [0x000070000a3d8000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000007955f7110> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
        at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
        at com.example.cs.executors.CSExecutorUnderstanding.lambda$2(CSExecutorUnderstanding.java:34)
        at com.example.cs.executors.CSExecutorUnderstanding$$Lambda$2/1705736037.run(Unknown Source)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

正如预期的那样,线程Worker-pool-main仍然处于WAITING状态。我对thread dump持怀疑态度。

由于是executor service管理executor framework中线程的生命周期,那么这个线程转储是如何从Thread.run()方法开始的。

难道不是executor的某些部分首先出现,然后Thread.run()

基本上,疑问是:当生命周期由executor管理时,为什么Thread.run()首先出现,堆栈上看到executors的部分。executors不是在启动这些线程吗,那么它们是如何在堆栈中出现的呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-22 10:12:41

当您启动一个新的Thread时,它将在一个全新的调用堆栈上执行其run方法。这是Thread中代码的入口点。它与名为start的线程完全解耦。“父”线程继续在自己的堆栈上独立运行自己的代码,如果这两个线程中的任何一个崩溃或完成,它不会影响另一个线程。

在线程的堆栈帧中唯一出现的东西是在run中调用的任何东西。您看不到是谁调用了run ( JVM做到了这一点)。当然,除非您将startrun混为一谈,并且直接从您自己的代码调用run。那么就根本不涉及新线程了。

在这里,线程不是由自己的代码直接创建的,而是由executor服务创建的。但是它没有做任何不同的事情,它还必须通过调用构造函数来创建线程并使用start启动它们。最终结果是一样的。

run通常所做的是委托给在其构造函数中设置的Runnable。您可以在这里看到: executor服务已经安装了一个ThreadPoolExecutor$Worker实例。这个包含在新线程上运行的所有代码,并控制它与执行器的交互。

然后,该ThreadPoolExecutor$Worker将调用其有效负载代码、应用程序代码、已提交给执行器的任务。在您的例子中,这是com.example.cs.executors.CSExecutorUnderstanding$$Lambda$2/1705736037

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61952435

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档