关于 Executors.newSingleThreadExecutor() 的问题

2024-05-02

这是一个关于以下代码的程序流程的问题:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {
    public static void main(String args[]) {
        ExecutorService service = null;
        try {
            service = Executors.newSingleThreadExecutor();
            
            System.out.println("begin");
            service.execute(() -> System.out.println("Printing zoo inventory"));
            service.execute(() -> {
                for(int i = 0; i< 3; i++)
                    System.out.println("Printing record: " + i);
            });
            service.execute(() -> System.out.println("printing zoo inventory"));
        } finally {
            if(service != null)
                service.shutdown();
        }
    }
}

在上面的代码中,一旦我们越过“System.out.println("begin")...线程执行器就会一个接一个地执行以下每个操作任务(基本上是一个 Runnable lambda)。

我的理解是,考虑到线程执行器“服务”执行,这些“任务”(s.o.p(“打印...”)、for循环、s.o.p(“打印..”))将一个接一个地运行线程执行器上的每个 Runnable lambda。

除非 Runnable lambda 在当前行完成,否则程序流程不会移动到下一行,我是否正确?例如,除非 Runnable lambda 完成 s.o.p("printing Zoo inventory")...它不会在下一行启动下一个 Runnable lambda 吗?

如果当前线程执行器带有计算密集型的 Runnable lambda,会发生什么情况?在这种情况下,下一行(如果它包含另一个 Runnable lambda)..必须等到当前线程执行器完成任务?


Q & A

-“我是否正确,除非无法运行的 lambda 在当前行完成,否则程序流程不会移动到下一行?例如,除非可运行的 lambda 完成 s.o.p(“打印动物园库存”)...它不会启动下一行的下一个可运行 lambda?”

- 是的,你是对的。*

-"如果当前线程执行器带有计算密集型的 Runnable lambda,会发生什么情况?在这种情况下, 下一行(如果它包含另一个 Runnable lambda)..必须 等到当前线程执行器完成任务?"

- 是的,必须等待。*

-"你最爱的颜色?"

-Red.

( * ) 假设您正在检查来自ExecutorService,忽略主线程(及其调用以执行某些操作),并专注于池工作线程。主线程由自己运行,如果他们决定,某些实现也可以向其分配任务,这就是本文的原因.



Test & Compare

我将尝试将此执行器与多线程执行器进行比较,以显示两种方法之间的差异。

关于您的问题,重点是阻塞等待场景,根据所使用的执行器服务,给出的答案完全不同。使用第二个选项,答案将是:

  • 如果有工作人员空闲,即使当前生产线尚未完成,它也可以移动到下一条生产线。

  • 不,如果线程可用,它就不必等待。

  • Red.

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).
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于 Executors.newSingleThreadExecutor() 的问题 的相关文章

  • eclipse行号状态行贡献项是如何实现的?

    我需要更新状态行编辑器特定的信息 我已经有了自己的实现 但我想看看 eclipse 贡献项是如何实现的 它显示状态行中的行号 列位置 谁能指点一下 哪里可以找到源代码 提前致谢 亚历克斯 G 我一直在研究它 它非常复杂 我不确定我是否了解完
  • 从 MATLAB 调用 Java?

    我想要Matlab程序调用java文件 最好有一个例子 需要考虑三种情况 Java 内置库 也就是说 任何描述的here http docs oracle com javase 6 docs api 这些项目可以直接调用 例如 map ja
  • 除非在后台线程中获取新的引用,否则存在潜在的引用计数问题

    我有一个second https stackoverflow com questions 28898966 prefer property accessor or kvc style for accessing core data prop
  • 将人类日期(当地时间 GMT)转​​换为日期

    我正在服务器上工作 服务器正在向我发送 GMT 本地日期的日期 例如Fri Jun 22 09 29 29 NPT 2018在字符串格式上 我将其转换为日期 如下所示 SimpleDateFormat simpleDateFormat ne
  • 提高 PostgreSQL 1 亿数据左连接查询性能

    我在用Postgresql 9 2 version Windows 7 64 bit RAM 6GB 这是一个Java企业项目 我必须在我的页面中显示订单相关信息 有三个表通过左连接连接在一起 Tables TV HD 389772 行 T
  • Java继承,扩展类如何影响实际类

    我正在查看 Sun 认证学习指南 其中有一段描述了最终修饰符 它说 如果程序员可以自由地扩展我们所知的 String 类文明 它可能会崩溃 他什么意思 如果可以扩展 String 类 我是否不会有一个名为 MyString 的类继承所有 S
  • 蓝牙发送和接收文本数据

    我是 Android 开发新手 我想制作一个使用蓝牙发送和接收文本的应用程序 我得到了有关发送文本的所有内容逻辑工作 但是当我尝试在手机中测试它时 我看不到界面 这是Main Activity Code import android sup
  • Jetty、websocket、java.lang.RuntimeException:无法加载平台配置器

    我尝试在 Endpoint 中获取 http 会话 我遵循了这个建议https stackoverflow com a 17994303 https stackoverflow com a 17994303 这就是我这样做的原因 publi
  • 如何将 HTML 链接放入电子邮件正文中?

    我有一个可以发送邮件的应用程序 用 Java 实现 我想在邮件中放置一个 HTML 链接 但该链接显示为普通字母 而不是 HTML 链接 我怎样才能将 HTML 链接放入字符串中 我需要特殊字符吗 太感谢了 Update 大家好你们好 感谢
  • 如何在JPanel中设置背景图片

    你好 我使用 JPanel 作为我的框架的容器 然后我真的想在我的面板中使用背景图片 我真的需要帮助 这是我到目前为止的代码 这是更新 请检查这里是我的代码 import java awt import javax swing import
  • 使用 Elastic Beanstalk 进行 Logback

    我在使用 Elastic Beanstalk 记录应用程序日志时遇到问题 我正在 AWS Elastic Beanstalk 上的 Tomcat 8 5 with Corretto 11 running on 64bit Amazon Li
  • 在 Java 中获取并存储子进程的输出

    我正在做一些需要我开始子处理 命令提示符 并在其上执行一些命令的事情 我需要从子进程获取输出并将其存储在文件或字符串中 这是我到目前为止所做的 但它不起作用 public static void main String args try R
  • 将 JScrollPane 添加到 JFrame

    我有一个关于向 Java 框架添加组件的问题 我有一个带有两个按钮的 JPanel 和一个添加了 JTable 的 JScrollPane 我想将这两个添加到 JFrame 中 我可以将 JPanel 添加到 JFrame 或将 JScro
  • Hibernate 本机查询 - char(3) 列

    我在 Oracle 中有一个表 其中列 SC CUR CODE 是 CHAR 3 当我做 Query q2 em createNativeQuery select sc cur code sc amount from sector cost
  • 列表过滤器内的 Java 8 lambda 列表

    示例 JSON id 1 products id 333 status Active id 222 status Inactive id 111 status Active id 2 products id 6 status Active
  • partitioningBy 必须生成一个包含 true 和 false 条目的映射吗?

    The 分区依据 https docs oracle com javase 8 docs api java util stream Collectors html partitioningBy java util function Pred
  • Java 正则表达式中的逻辑 AND

    是否可以在 Java Regex 中实现逻辑 AND 如果答案是肯定的 那么如何实现呢 正则表达式中的逻辑 AND 由一系列堆叠的先行断言组成 例如 foo bar glarch 将匹配包含所有三个 foo bar 和 glarch 的任何
  • Log4j2 ThreadContext 映射不适用于parallelStream()

    我有以下示例代码 public class Test static System setProperty isThreadContextMapInheritable true private static final Logger LOGG
  • Android View Canvas onDraw 未执行

    我目前正在开发一个自定义视图 它在画布上绘制一些图块 这些图块是从多个文件加载的 并将在需要时加载 它们将由 AsyncTask 加载 如果它们已经加载 它们只会被绘制在画布上 这工作正常 如果加载了这些图片 AsyncTask 就会触发v
  • 抛出 Java 异常时是否会生成堆栈跟踪?

    这是假设我们不调用 printstacktrace 方法 只是抛出和捕获 我们正在考虑这样做是为了解决一些性能瓶颈 不 堆栈跟踪是在构造异常对象时生成的 而不是在抛出异常对象时生成的 Throwable 构造函数调用 fillInStack

随机推荐