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

CuriousMind:

我写了下面的程序。基本上我是executor framework用来管理线程的。我还使用了a 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()method 开始

难道不应该是executor出现的第一部分,然后Thread.run()

基本上,疑问是:当生命周期受其管理时executor,那么如何Thread.run()首先出现并在堆栈中看到的一部分executorsexecutors启动这些线程,那么它们如何出现在堆栈中?

锡洛:

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

出现在线程堆栈框架中的唯一东西是在里面被调用的东西run您不会看到谁调用了run(JVM做到了)。当然,除非您start自己的代码混淆runrun直接调用这样就根本不涉及新线程。

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

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

ThreadPoolExecutor$Worker反过来会再打电话到其有效载荷的代码,你的应用程序代码,已提交给执行任务。就您而言,就是com.example.cs.executors.CSExecutorUnderstanding$$Lambda$2/1705736037

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章