Why does the Java ExecutorService newSingleThreadExecutor spawn two threads?

I have an example java code below which, if it runs as a console application, behaves as I expected (creating a single thread to run runnable).

Strange behavior (spawning two threads - example below) I see when I run this sample as a service application using Apache prunsrv64.exe.

I am testing this on a Windows 7 - 64bit machine.

Output Example:

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 

Code example:

 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: To clarify, I call this code as follows:

  ExecutorTest tester = new ExecutorTest(); tester.testIt(); 

The same code, without changes, behaves differently when run as a console application and a service application, as I mentioned above.


Update 2: I added a second tester that uses the ScheduledExecutorService. The behavior of the same.

Update 2:

 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 code 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(); 

Update 3: Modified logging to add authentication 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 
+6
source share
2 answers

The only reasonable conclusion is that you (or the framework) create two ExecutorTest links and execute it twice.

Add the HashCode id 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, behaves differently when run as a console application and a service application, as I mentioned above.

You determine exactly how many of them are created here.


Change Based on the third update.

My guess is correct, the System.identityHashCode object of the object is similar to the location of its memory. As you can see, these two values ​​are different, but if the ExecutorService created two threads, these values ​​would be the same.

This means that you are creating multiple instances. You may not be direct, but the structure creates several identical services and starts them.

So, this is connected with the question "why does the executing service create 2 threads" in "why does my infrastructure create two instances of the service". I cannot answer this question.

To clarify, imagine running your test as follows

 ExecutorTest tester1 = new ExecutorTest(); tester1.testIt(); ExecutorTest tester2 = new ExecutorTest(); tester2.testIt(); 

This is similar to what is happening in your application.

+4
source

I really tried this code on my computer for example

     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 get only one stream,

  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 in most cases an error may occur in the way you create the class

+1
source

Source: https://habr.com/ru/post/979113/


All Articles