Q & A
-“我是否正确,除非无法运行的 lambda 在当前行完成,否则程序流程不会移动到下一行?例如,除非可运行的 lambda 完成 s.o.p(“打印动物园库存”)...它不会启动下一行的下一个可运行 lambda?”
- 是的,你是对的。*
-"如果当前线程执行器带有计算密集型的 Runnable lambda,会发生什么情况?在这种情况下,
下一行(如果它包含另一个 Runnable lambda)..必须
等到当前线程执行器完成任务?"
- 是的,必须等待。*
-"你最爱的颜色?"
-Red.
( * ) 假设您正在检查来自ExecutorService
,忽略主线程(及其调用以执行某些操作),并专注于池工作线程。主线程由自己运行,如果他们决定,某些实现也可以向其分配任务,这就是本文的原因.
Test & Compare
我将尝试将此执行器与多线程执行器进行比较,以显示两种方法之间的差异。
关于您的问题,重点是阻塞等待场景,根据所使用的执行器服务,给出的答案完全不同。使用第二个选项,答案将是:
SingleThreadExecutor
创建一个Executor that 使用单个工作线程 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newSingleThreadExecutor(java.util.concurrent.ThreadFactory)操作关闭
无界队列。
任务是
保证顺序执行,并且不会超过一个任务
在任何给定时间都活跃.
池中只有一个线程,因此所有任务都分配给它。正如文档中所述,它必须按顺序执行所有这些操作。做一个简单的测试,例如:
service = Executors.newSingleThreadExecutor();
service.execute(() -> System.out.println("Printing zoo inventory"));
service.execute(() -> {
try {Thread.sleep(5000); System.out.println("Woke up"); }
catch (InterruptedException e) {e.printStackTrace();}
});
service.execute(() -> System.out.println("Finish"));
Output
Printing zoo inventory // ---- [Thread 1]
//...5s
Woke up // ---- [Thread 1]
Finish // ---- [Thread 1] -{x}-
正如这张至少平庸的时间图所示:
{task1} {task2} {task3}
^ ^ ^
| | (~5s) |
[Thread1]-->[Thread1]---------------------->[Thread1]->{x}
调试它时,唯一可用的线程确认它是执行前两个任务的线程。图像示例来自原始OP的问题:
第三个任务的断点 - 已经完成了两个
MultiThreaded Pool https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool(int)
使用FixedThreadPool
例如。当多个工作线程可用时,进程的行为会发生变化;对于本示例,设置了两个线程。
一如既往,应该仔细阅读文档:
创建一个重用线程池固定数量的线程 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool(int)操作
脱离共享无界队列。在任何时候,最多 nThreads 个线程
将是主动处理任务。如果提交了额外的任务
当所有线程都处于活动状态时,它们将在队列中等待,直到
线程可用
稍微修改了测试,添加一些有关工作线程的信息并执行一些额外的任务。
volatile boolean wifeAlarm = false;
//...
service = Executors.newFixedThreadPool(2);
设置完成后,执行多个任务:
service.execute(() -> System.out.println("Woke up fast -"
+ Thread.currentThread().getName()));
service.execute(() ->
{
try {
Thread.sleep(5000);
System.out.println("Woke up lazy - John where are you?? - {"+
Thread.currentThread().getName()+"}");
} catch (InterruptedException e){}
finally { wifeAlarm=true;}
});
service.execute(() -> System.out.println("Cleaning - {"
+ Thread.currentThread().getName()+"}"));
service.execute(() -> System.out.println("Making breakfast - {"
+Thread.currentThread().getName()+"}"));
service.execute(() -> System.out.println("Flirt with neighbour - {"
+Thread.currentThread().getName()+"}"));
service.execute(() -> System.out.println("Got her number - {"
+Thread.currentThread().getName()+"}"));
service.execute(() -> System.out.println("Send hot af pic - {"
+Thread.currentThread().getName()+"}"));
service.execute(() -> System.out.println("Remove all proof on phone - {"
+Thread.currentThread().getName()+"}"));
service.execute(() ->
{
try {
while (!wifeAlarm)
Thread.sleep(13);
System.out.println("Just working my love - {"+
Thread.currentThread().getName()+"}");
} catch (InterruptedException e) {}
});
Output
Woke up fast - {pool-1-thread-1}
Cleaning - {pool-1-thread-1}
Making breakfast - {pool-1-thread-1}
Flirt with neighbour - {pool-1-thread-1}
Got her number - {pool-1-thread-1}
Send hot af pic - {pool-1-thread-1}
Remove all proof on phone - {pool-1-thread-1}
// ~4-5s
Woke up lazy - John where are you?? - {pool-1-thread-2}
Just working my love - {pool-1-thread-1}
这只是另一种可怕的表现:
{task1} {task2} {task3} (..) {task9}
^ ^ ^ ^ (~5s)
| [Thread2]--- | -------------|---------(...)----------->{x}
[Thread1] ----->[Thread1]--(..)-[Thread1]----------------------->{x}
简历中:约翰利用了这个新环境,取得了一些成就great感谢多线程池。
John 能够执行 7 个操作,而线程 2 执行 1 个操作。对于 John 来说更好的是,他能够在线程 2 完成分配的任务之前完成所有操作。约翰现在安全了,它将完成其任务并进入空闲状态,因为队列是空的。对约翰有好处。
-
thread-2
被安排了task 2。但这次睡眠不会导致工作队列的增加,因为其他线程能够同时执行它们。
-
thread-1
执行所有的4 vital tasks: 5、6、7 和 8。它还被分配了其他4个低优先级任务,能够在另一个线程“忙”时清空工作队列(sleeping).