当前位置: 首页 > 知识库问答 >
问题:

ExecutorService的执行和thread.run在Java并发运行线程之间有什么区别?

危裕
2023-03-14

我不熟悉java中的并发编程,并提出了以下场景,在这些场景中,我不知道何时使用哪个

场景1:在下面的代码中,我试图通过调用GPSService类上的.start()来运行线程,这是一个可运行的实现。

int clientNumber = 0;
ServerSocket listener = new ServerSocket(port);

while (true) {
            new GPSService(listener.accept(), clientNumber++, serverUrl).start();
} 

场景2:在下面的代码中,我试图使用ExecutorService类运行线程,如图所示

int clientNumber = 0;
ServerSocket listener = new ServerSocket(port);
while(true) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.execute(new GPSService(listener.accept(), client++, serverUrl));

        executor.shutdown();
        while (!executor.awaitTermination(1, TimeUnit.SECONDS)) {
            // Threads are still running
            System.out.println("Thread is still running");
        }
        // All threads are completed
        System.out.println("\nThread completed it's execution and terminated successfully\n");              
}

我的问题是
在并发编程中调用线程的最佳实践是什么?
当我使用第一个或第二个线程时,会产生什么结果(麻烦)<注意:在第一个场景中,每隔几天程序就会被挂起,我一直面临一个问题。那么,当我使用第一种方法时,这个问题与我的预期有关吗?
任何好的/有用的答案都将不胜感激:)谢谢

共有2个答案

锺离嘉容
2023-03-14

oracle留档自执行器

public static ExecutorService newCachedThreadPool()

创建一个线程池,该线程池根据需要创建新线程,但在以前构造的线程可用时将重用这些线程。这些池通常会提高执行许多短期异步任务的程序的性能。

要执行的调用将重用以前构造的线程(如果可用)。如果没有可用的现有线程,将创建一个新线程并将其添加到池中。六十秒未使用的线程将终止并从缓存中删除。

因此,保持空闲足够长时间的池不会消耗任何资源。请注意,具有类似属性但不同细节(例如,超时参数)的池可以使用ThreadPoolExec导师构造函数创建。

public static ExecutorService newFixedThreadPool(int nThreads)

创建一个线程池,该线程池重用在共享无界队列上运行的固定数量的线程。在任何时候,最多nThread线程将是活动的处理任务。如果在所有线程都处于活动状态时提交了其他任务,则它们将在队列中等待,直到线程可用。

如果任何线程在关机之前的执行过程中由于故障而终止,那么如果需要执行后续任务,将使用一个新线程代替它。池中的线程将一直存在,直到显式关闭。

@Giovanni说您不必向newCachedThreadPool提供线程数,这与newFixedThreadPool()不同,后者必须通过线程池中线程数的最大上限。

但在这两者之间,newFixedThreadPool()是首选newCachedThread池可能会导致泄漏,并且由于无边界的性质,您可能会达到可用线程的最大数量。有些人认为这是一种罪恶。

查看相关SE问题:

为什么通过newCachedThreadpool创建的ExecutorService是邪恶的?

谷玉韵
2023-03-14

除了在Scenario2中管理线程终止之外,您发布的两个场景没有太大区别;您总是为每个传入请求创建一个新线程。如果您想使用线程池,我的建议不是为每个请求创建一个线程池,而是为每个服务器创建一个线程池并重用线程。比如:

public class YourClass {

//in init method or constructor 
ExecutorService executor = Executors....;// choose from newCachedThreadPool() or newFixedThreadPool(int nThreads) or some custom option


int clientNumber = 0;
ServerSocket listener = new ServerSocket(port);
while(true) {

    executor.execute(new GPSService(listener.accept(), client++, serverUrl));

}

这将允许您使用线程池,并控制服务器使用多少线程。如果您想使用执行人,这是首选的方式。

对于服务器池,您需要决定池中有多少线程;您有不同的选择,但您可以开始或使用固定数量的线程或尝试使用非忙线程的池,如果所有线程都忙它创建一个新的(newCachedThreadpool())。要分配的线程数取决于许多因素:并发请求的数量和持续时间。您的服务器端代码花费的时间越多,您就越需要额外的线程。如果您的服务器端代码非常快,那么池很有可能回收已经分配的线程(因为请求不会在同一瞬间全部出现)。

例如,假设您在一秒钟内有10个请求,每个请求持续0.2秒;如果请求到达0,0.1,0.2,0.3,0.4,0.5。。第二部分(例如,2015年6月23日7:16:00:00、2015年6月23日7:16:00:01、2015年6月23日7:16:00:02)您只需要三个线程,因为0.3处的请求可以由处理第一个请求(0处的请求)的线程执行,依此类推(0.4处的请求可以重用0.1处的请求所使用的线程)。由三个线程管理的十个请求。

我建议您(如果您还没有读过的话)在实践中阅读Java并发(任务执行在第6章);这是一本关于如何用Java构建并发应用程序的好书。

 类似资料:
  • 问题内容: 进程和线程之间的技术区别是什么? 我感到像“过程”这样的词已被过度使用,并且还有硬件和软件线程。像Erlang这样的语言的轻量级进程怎么样?有确定的理由使用一个术语而不是另一个术语吗? 问题答案: 进程和线程都是独立的执行序列。典型的区别是(同一进程的)线程在共享内存空间中运行,而进程在单独的内存空间中运行。 我不确定您可能指的是“硬件”还是“软件”线程。线程是一种操作环境功能,而不是

  • 本文向大家介绍ScheduledThread池和单线程执行器之间的区别。,包括了ScheduledThread池和单线程执行器之间的区别。的使用技巧和注意事项,需要的朋友参考一下 序号 键 预定线程池 单线程执行器 1 基本的 创建一个线程池,该线程池可以安排命令在给定的延迟后运行或定期执行。  确保任务按顺序执行,并且在任何给定时间都不会激活一个以上的任务 2 队列 它使用延迟队列存储任务。根据

  • 欢迎阅读我的Java8并发教程的第一部分。这份指南将会以简单易懂的代码示例来教给你如何在Java8中进行并发编程。这是一系列教程中的第一部分。在接下来的15分钟,你将会学会如何通过线程,任务(tasks)和 exector services来并行执行代码。 并发在Java5中首次被引入并在后续的版本中不断得到增强。在这篇文章中介绍的大部分概念同样适用于以前的Java版本。不过我的代码示例聚焦于Ja

  • 问题内容: 查找许多选项以运行映射减少程序。谁能解释下面这些命令之间的区别。以及对Map-reduce工作的影响(如果有)。 在这些命令中,哪个最好? 是否可以使用以下命令中的Web服务端口8088(YARN),使配置像使用Web服务上的Yarn和Job History(如display Hadoop和yarn命令)正常显示有关作业的所有信息一样? 问题答案: 他们中没有一个比另一个更好。执行命令

  • 问题内容: 这可能是一个基本问题,我对此感到困惑, 在一个文件中,我是这样的: 现在在另一个文件中我有这个: 所以在上面两种情况之间有什么区别,情况1是否正在创建新线程,情况2是否未创建线程?那是我的猜测…希望大家能更好地回答。谢谢 问题答案: 在新线程中运行代码。直接调用不会在新线程中执行,而是从中调用该线程。 如果直接调用,则没有线程。直接调用将阻塞,直到完成任何代码。 创建一个新线程,并且由

  • 本文向大家介绍lodash和下划线之间有什么区别?,包括了lodash和下划线之间有什么区别?的使用技巧和注意事项,需要的朋友参考一下 lodash和underscore都是实用程序库,它们通过提供使数组,数字,对象,字符串等的使用更加容易的实用程序,使JavaScript变得更容易。这些库非常适合- 迭代数组,对象和字符串 操作和测试值 创建复合函数 它们都是功能库。Lo-Dash是Unders