我有一个示例java代码,如果作为控制台应用程序运行,则表现得像我预期的那样(产生一个线程来执行runnable)。
奇怪的行为(产生两个线程 - 下面的示例)我看到的是当我使用Apache的prunsrv64.exe将此示例作为服务应用程序运行时。
我正在Windows 7计算机上测试 - 64位。
示例输出:
Thread -28 Current time: 09:50:11 AM
Thread -52 Current time: 09:50:12 AM
Thread -28 Current time: 09:50:21 AM
Thread -52 Current time: 09:50:22 AM
Thread -28 Current time: 09:50:31 AM
Thread -52 Current time: 09:50:32 AM
示例代码:
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorTest{
public void testIt(){
ExecutorService ex = Executors.newSingleThreadExecutor();
ex.execute(new Runnable(){
public void run() {
while(true){
System.out.printf("Thread -" + Thread.currentThread().getId() + " Current time: %tr%n", new Date());
try{
Thread.sleep(10000);
}catch(InterruptedException ie){
ie.printStackTrace();
}
}
}
});
}
}
感谢。
更新: 只是为了澄清我正在调用此代码如下:
ExecutorTest tester = new ExecutorTest();
tester.testIt();
如上所述,当作为控制台应用程序和服务应用程序运行时,没有更改的相同代码的行为会有所不同。
更新2: 我添加了第二个使用ScheduledExecutorService的测试人员。行为是一样的。
Update2输出:
Using ScheduledExecutorService.
Thread Id outside Runnable -1
Thread -53 Current time: 10:58:15 AM
Thread -28 Current time: 10:58:24 AM
Thread -53 Current time: 10:58:25 AM
Thread -28 Current time: 10:58:34 AM
Thread -53 Current time: 10:58:35 AM
Thread -28 Current time: 10:58:44 AM
Thread -53 Current time: 10:58:45 AM
Thread -28 Current time: 10:58:54 AM
Thread -53 Current time: 10:58:55 AM
Thread -28 Current time: 10:59:04 AM
Thread -53 Current time: 10:59:05 AM
更新2代码:
public void testItWithScheduled(){
System.out.println("Using ScheduledExecutorService.");
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
System.out.println("Thread Id outside Runnable -" + Thread.currentThread().getId());
ex.scheduleWithFixedDelay(new Runnable(){
public void run() {
System.out.printf("Thread -" + Thread.currentThread().getId() + " Current time: %tr%n", new Date());
}
},0L, 10, TimeUnit.SECONDS);
}
called through:
ExecutorTest tester = new ExecutorTest();
tester.testItWithScheduled();
更新3: 修改日志记录以添加标识哈希
Using ScheduledExecutorService.
Thread Id outside Runnable 1 with reference: 1370756928
Thread -53 Current time: 11:10:38 AM with reference: 1370756928
Thread -28 Current time: 11:10:47 AM with reference: 1939972532
Thread -53 Current time: 11:10:48 AM with reference: 1370756928
Thread -28 Current time: 11:10:57 AM with reference: 1939972532
Thread -53 Current time: 11:10:58 AM with reference: 1370756928
Thread -28 Current time: 11:11:07 AM with reference: 1939972532
Thread -53 Current time: 11:11:08 AM with reference: 1370756928
答案 0 :(得分:4)
唯一合理的结论是你(或框架)正在创建ExecutorTest
的两个引用并执行两次。
将对象的identityHashCode添加到日志记录中。
System.out.printf("Thread -" + Thread.currentThread().getId() + " Current time: %tr with reference: %s%n ", new Date(), System.identityHashCode(ExecutorTest.this));
如上所述,当作为控制台应用程序和服务应用程序运行时,没有更改的相同代码的行为会有所不同。
您可以精确控制在此创建的数量。
修改根据您的第三次更新。
我的假设是正确的,对象的System.identityHashCode
类似于其内存位置。如您所见,这两个值不同,但如果ExecutorService
创建了两个线程,那么这些值将是相同的。
这意味着您正在创建多个实例。也许不是你直接,但框架正在创建多个相同的服务并运行它们。
因此,这从'为什么执行者服务创建2个线程'到'为什么我的框架创建两个服务实例'的问题。这个问题我无法回答。
为了更清楚地说明,想象一下像这样执行你的测试
ExecutorTest tester1 = new ExecutorTest();
tester1.testIt();
ExecutorTest tester2 = new ExecutorTest();
tester2.testIt();
这与您的应用程序中发生的情况类似。
答案 1 :(得分:1)
我实际上在我的电脑上尝试过这样的代码,
import java.util.Date; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ExecutorTest{ public void testIt(){ ExecutorService ex = Executors.newSingleThreadExecutor(); ex.execute(new Runnable(){ public void run() { while(true){ System.out.printf("Thread -" + Thread.currentThread().getId() + " Current time: %tr%n", new Date()); try{ Thread.sleep(1000); }catch(InterruptedException ie){ ie.printStackTrace(); } } } }); } public static void main(String[] args) { ExecutorTest x = new ExecutorTest(); x.testIt(); } }
我只得到一个帖子,
Thread -10 Current time: 09:50:27 PM Thread -10 Current time: 09:50:28 PM Thread -10 Current time: 09:50:29 PM Thread -10 Current time: 09:50:30 PM Thread -10 Current time: 09:50:31 PM Thread -10 Current time: 09:50:32 PM Thread -10 Current time: 09:50:33 PM
因此大多数情况下,您实例化类
的方式可能会出错