Java 由executor framework管理的线程的线程转储
我编写了以下程序。基本上,我使用Java 由executor framework管理的线程的线程转储,java,multithreading,executorservice,Java,Multithreading,Executorservice,我编写了以下程序。基本上,我使用executor框架来管理线程。我还使用了阻塞队列,并故意将其保持为空,以便线程保持等待状态 以下是程序: package com.example.executors; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util
executor框架
来管理线程。我还使用了阻塞队列
,并故意将其保持为空,以便线程保持等待状态
以下是程序:
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);
}
}
正如预期的那样,线程Worker pool main
仍处于WAITING
状态。我的疑问在于线程转储
由于是executor服务
管理executor框架
中线程的生命周期,那么这个线程转储是如何从thread.run()
方法开始的
是不是应该先出现executor
的某些部分,然后出现Thread.run()
基本上,疑问在于:当生命周期由
执行器
管理时,那么Thread.run()
为什么会出现在堆栈的最前面,请参见执行器的部分。executors
不是在启动这些线程吗,那么它们是如何在堆栈中出现的呢?当您启动一个新的线程时,它将在一个全新的调用堆栈上执行其run
方法。这是该线程中代码的入口点。它与调用start
的线程完全解耦。“父”线程继续在自己的堆栈上独立运行自己的代码,如果两个线程中的任何一个崩溃或完成,则不会影响另一个线程
线程堆栈帧中显示的唯一内容是run
内部调用的内容。您无法看到谁调用了run
(JVM就是这么做的)。当然,除非您将start
与run
混淆,并直接从自己的代码调用run
。那么就根本没有新的线索了
这里,线程不是由您自己的代码直接创建的,而是由executor服务创建的。但这并没有什么不同,它还必须通过调用构造函数来创建线程,并使用start
启动它们。最终结果是一样的
run
通常会委托给构造函数中设置的Runnable
。您可以在这里看到:executor服务安装了一个ThreadPoolExecutor$Worker
实例。这个包含所有要在新线程上运行的代码,并控制它与执行器的交互
该ThreadPoolExecutor$Worker
随后将调用其有效负载代码、应用程序代码以及已提交给执行器的任务。在您的情况下,就是com.example.cs.executors.CSExecutorUnderstanding$$Lambda$2/1705736037
谢谢您提供详细信息。我必须承认,线程转储
不是我的专长,但有时我需要这样做。根据你推断信息的方式,我很难做到。大多数情况下,在线呈现的信息“只是基本信息,而且非常明显”。任何关于如何改进获取“真实”细节的指导。您如何推断com.example.cs.executors.CSExecutorUnderstanding$$Lambda$2/1705736037
。有关于如何改进的建议吗?不知道你的意思。堆栈跟踪中的每一行都对应于另一个方法调用的一个方法(它下面的那一行)。关于CSExecutorUnderstanding的代码就是您提交到runnable中的代码。上面提到的所有其他类都来自JDK标准库。您可以查看ThreadPoolExecutor.java:624
的源代码,然后按照那里的调用进行操作。我会详细介绍一下,谢谢您的回答。以防万一,如果我有后续问题,希望你能帮助我。最好的
"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)