问题
I have a sample java code below which if run as a console application behaves as I expected ( spawning a single thread to execute the runnable).
The strange behavior (spawning two threads - sample below) I see is when I run this sample as a service application using Apache's prunsrv64.exe.
I am testing this on a Windows 7 machine - 64bit.
Sample Output:
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
Sample Code:
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();
}
}
}
});
}
}
Thanks.
Update: Just to clarify I am calling this code as follows:
ExecutorTest tester = new ExecutorTest();
tester.testIt();
The same code without changes is behaving differently when run as console application and a service application as I mentioned above.
Update 2: I added a second tester which uses a ScheduledExecutorService. The behavior is the same.
Update2 Output:
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
Update 2 Code:
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();
Update 3: Modified logging to add identity hash
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
回答1:
The only reasonable conclusion is that you (or the framework) are creating two references of ExecutorTest
and executing it twice.
Add the identityHashCode of the object to your logging.
System.out.printf("Thread -" + Thread.currentThread().getId() + " Current time: %tr with reference: %s%n ", new Date(), System.identityHashCode(ExecutorTest.this));
The same code without changes is behaving differently when run as console application and a service application as I mentioned above.
You control exactly how many are being created here.
Edit Based on your third update.
My assumption is correct, the System.identityHashCode
of an object is analogous to its memory location. As you can see the two values are different but if the ExecutorService
was creating two threads, those values would be the same.
That means you are creating multiple instances. Maybe not you directly, but the framework is creating multiple of the same service and running them.
So this moves from a question of 'why is the executor service creating 2 threads' to 'why is my framework creating two service instances'. That question I cannot answer.
To clarify more clearly, imagine executing your test like this
ExecutorTest tester1 = new ExecutorTest();
tester1.testIt();
ExecutorTest tester2 = new ExecutorTest();
tester2.testIt();
That is similar to what is occurring in your application.
回答2:
I actually tried this code in my pc like this ,
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(); } }
and I m getting only one thread,
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
so mostly there can be an error on the way you are instantiating the class
来源:https://stackoverflow.com/questions/27297306/why-is-java-executorservice-newsinglethreadexecutor-spawning-two-threads