Why is java ExecutorService newSingleThreadExecutor spawning two threads?

淺唱寂寞╮ 提交于 2020-01-14 07:37:07

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!