由执行者框架管理的线程的线程转储

问题描述 投票:1回答:1

我已经编写了以下程序。基本上,我使用executor framework来管理线程。我还使用了BlockingQueue并故意将其保留为空,以便线程保持等待状态。

下面是程序:


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);
    }
}

一旦程序运行,由于Thread.sleep(),main thread仍处于TIMED_WAITING状态。在由执行者管理的线程中,我使它读取一个空的阻塞队列,并且该线程永远保持在WAITING状态。我想看看在这种情况下thread dump的外观如何。我在下面捕获了它:

"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是否不启动这些线程,所以它们如何出现在堆栈中?

java multithreading executorservice
1个回答
2
投票

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

唯一出现在线程的堆栈帧中的是run内部被调用的内容。您不会看到谁调用了run(JVM做到了)。当然,除非您将startrun混淆,然后直接从您自己的代码中调用run。这样就根本不涉及任何新线程。

这里,线程不是由您自己的代码直接创建的,而是由执行程序服务创建的。但这并没有什么不同,它还必须通过调用构造函数来创建线程,并使用start启动它们。最终结果是相同的。

run通常所做的是委派给已在其构造函数中设置的Runnable。您将在此处看到以下内容:执行程序服务已安装ThreadPoolExecutor$Worker实例。此代码包含要在新线程上运行并控制其与执行程序的交互的所有代码。

然后,ThreadPoolExecutor$Worker随后将调用其有效负载代码,您的应用程序代码,已提交给执行者的任务。您的情况是com.example.cs.executors.CSExecutorUnderstanding$$Lambda$2/1705736037

© www.soinside.com 2019 - 2024. All rights reserved.