我写了下面的程序。基本上我是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()
首先出现并在堆栈中看到的一部分executors
。不executors
启动这些线程,那么它们如何出现在堆栈中?
当启动new时Thread
,它将run
在全新的调用堆栈上执行其方法。那是该代码的入口点Thread
。它与调用的线程完全分离start
。“父”线程继续在其自己的堆栈上独立运行其自己的代码,并且如果两个线程中的任何一个崩溃或完成,它都不会影响另一个线程。
出现在线程堆栈框架中的唯一东西是在里面被调用的东西run
。您不会看到谁调用了run
(JVM做到了)。当然,除非您start
与自己的代码混淆run
并run
直接调用。这样就根本不涉及新线程。
在这里,线程不是由您自己的代码直接创建的,而是由执行程序服务创建的。但这并没有什么不同,它还必须通过调用构造函数来创建线程,并使用来启动它们start
。最终结果是相同的。
什么run
通常不会是委托给一个Runnable
已在它的构造函数中设置。您将在此处看到以下内容:executor服务已安装ThreadPoolExecutor$Worker
实例。此代码包含要在新线程上运行并控制其与执行程序的交互的所有代码。
这ThreadPoolExecutor$Worker
反过来会再打电话到其有效载荷的代码,你的应用程序代码,已提交给执行任务。就您而言,就是com.example.cs.executors.CSExecutorUnderstanding$$Lambda$2/1705736037
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句