在以下给定的代码段中:
private ExecutorService executor = Executors.newFixedThreadPool(2); //create a fixed thread pool
executor.execute(new Thread(() -> foo()));
executor.execute(new Thread(() -> foo()));
executor.execute(new Thread(() -> foo()));
在上面的示例中,创建了2个或3个线程有多少个?
为什么不使用
executor.execute(Callable);
? 最佳答案
从根本上讲:不要将Thread
与 execute
一起使用,而要使用Runnable
。如您所述,ExecutorService
的工作就是处理线程。
您已经在注释中澄清了您的意思是那里的OS线程。
两个或五个(全线或光纤)。几乎可以肯定不是三个。可能是一或四个。好的精确答案。 :-)原因如下:
明确地创建了三个Thread
实例。这并不意味着已经创建了三个OS线程。用于Thread
的JavaDoc并未明确指出在创建Thread
对象时或稍后(如果/或在调用start
时)创建了OS线程,这很可能取决于实现。由于您从不调用start
,因此我们不知道为这些Thread
实例创建任何操作系统线程。
因此,就操作系统线程而言,可能是:
ExecutorService
以及创建服务时设置的限制为两个线程的事实,由execute
创建和启动一个或两个。最初,我以为在给定这三个调用后肯定会创建两个线程,但是Aleksandr Semyannikov在a comment中指出ExecutorService
可能不必创建两个线程。这些execute
调用计划的工作只是一个方法调用(尽管我们不知道该方法需要运行多长时间)。因此,它可能仅能重用一个线程。我倾向于对此表示怀疑(我认为在创建第二个线程时,第一个线程仍将分配给第一个execute
调用),但是我对此的置信度不超过60%。 :-)如果它真的很重要,我会对其进行测试(尽管只是暂时,我不确定如何进行测试)。 new Thread
创建,一两个由ExecutorService
创建并启动。 我的钱是两个。
我认为我们可以排除三个。要获得答案三,
ExecutorService
实现必须使用您传递的线程,几乎可以肯定不会。在我的Linux系统上,我可以确认我的Java版本从15个(!)线程开始,并且当上面的代码运行时,还会创建两个。我还可以确认那些线程是池线程,而不是
new Thread
中的线程。我使用了现成的代码:import java.util.*;
import java.util.concurrent.*;
public class Example {
private static void foo() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) throws Exception {
System.out.println("Waiting...");
Thread.currentThread().sleep(20000);
System.out.println("Starting...");
ExecutorService executor = Executors.newFixedThreadPool(2); //create a fixed thread pool
executor.execute(new Thread(() -> foo()));
executor.execute(new Thread(() -> foo()));
executor.execute(new Thread(() -> foo()));
}
}
在20年代期间,等待使用
ps aux | grep java
来获取进程的PID,并使用top -H -pPID
(其中PID是pid)来查看线程。关于java - 为什么Java ExecutorService execute采用新的Runnable实现,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58874326/