由执行器框架管理的线程的线程转储
Thread dump for threads which are managed by executor framework
我写了下面的程序。基本上我使用 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(CSExecutorUnderstanding.java:34)
at com.example.cs.executors.CSExecutorUnderstanding$$Lambda/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.access1(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
不是在启动这些线程吗,那么它们是如何出现在堆栈中的?
当您启动一个新的 Thread
时,它将在一个全新的调用堆栈上执行其 run
方法。那是 Thread
中代码的入口点。它与调用 start
的线程完全分离。 "parent" 线程继续 运行 独立地在自己的堆栈上编写自己的代码,如果两个线程中的任何一个崩溃或完成,它都不会影响另一个。
线程堆栈帧中唯一显示的是在 run
中调用的内容。您看不到谁调用了 run
(JVM 做到了)。当然,除非您将 start
与 run
混淆并直接从您自己的代码中调用了 run
。然后根本就没有涉及新的线程。
这里线程不是自己代码直接创建的,而是executor服务创建的。但是那个没有做任何不同,它也必须通过调用构造函数创建线程并使用 start
启动它们。最终结果是一样的。
run
通常做的是委托给已在其构造函数中设置的 Runnable
。您会在此处看到:执行程序服务已安装 ThreadPoolExecutor$Worker
实例。这个包含所有代码 运行 在新线程上并控制它与执行程序的交互。
然后 ThreadPoolExecutor$Worker
将依次调用其有效负载代码、您的应用程序代码以及已提交给执行程序的任务。在您的情况下,即 com.example.cs.executors.CSExecutorUnderstanding$$Lambda/1705736037
.
我写了下面的程序。基本上我使用 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(CSExecutorUnderstanding.java:34)
at com.example.cs.executors.CSExecutorUnderstanding$$Lambda/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.access1(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
不是在启动这些线程吗,那么它们是如何出现在堆栈中的?
当您启动一个新的 Thread
时,它将在一个全新的调用堆栈上执行其 run
方法。那是 Thread
中代码的入口点。它与调用 start
的线程完全分离。 "parent" 线程继续 运行 独立地在自己的堆栈上编写自己的代码,如果两个线程中的任何一个崩溃或完成,它都不会影响另一个。
线程堆栈帧中唯一显示的是在 run
中调用的内容。您看不到谁调用了 run
(JVM 做到了)。当然,除非您将 start
与 run
混淆并直接从您自己的代码中调用了 run
。然后根本就没有涉及新的线程。
这里线程不是自己代码直接创建的,而是executor服务创建的。但是那个没有做任何不同,它也必须通过调用构造函数创建线程并使用 start
启动它们。最终结果是一样的。
run
通常做的是委托给已在其构造函数中设置的 Runnable
。您会在此处看到:执行程序服务已安装 ThreadPoolExecutor$Worker
实例。这个包含所有代码 运行 在新线程上并控制它与执行程序的交互。
然后 ThreadPoolExecutor$Worker
将依次调用其有效负载代码、您的应用程序代码以及已提交给执行程序的任务。在您的情况下,即 com.example.cs.executors.CSExecutorUnderstanding$$Lambda/1705736037
.