6

У меня есть пример java-кода, ниже которого, если он запускается как консольное приложение, ведет себя так, как я ожидал (создавая один поток для выполнения runnable).Почему java ExecutorService newSingleThreadExecutor порождает два потока?

Странное поведение (порождение двух потоков - пример ниже) Я вижу, когда я запускаю этот образец в качестве приложения-приложения с помощью apun's 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(); 
        }     
       } 

      } 
     });  
    } 
} 

Спасибо.

Update: Просто для уточнения я называю этот код следующим образом:

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 

Update 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: Модифицированный каротаж добавить идентичности окрошка

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

Возможно, вы просто вызываете 'testIt' дважды? –

+0

Я бы предположил, что у вас есть ваш основной поток, запускающий программу, а затем вы создаете 'Executors.newSingleThreadExecutor();' который создает другой поток. Результат состоит из двух потоков. –

+0

У вас есть 2 разных идентификатора потоков, если вы поместите println getId() прямо перед циклом while? – brummfondel

ответ

4

Единственный разумный мошенника clus заключается в том, что вы (или фреймворк) создаете две ссылки ExecutorTest и выполняете ее дважды.

Добавьте идентификаторHashCode объекта в ваш журнал.

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

Это подобно тому, что происходит в вашем приложении.

+0

John, я изменил регистрацию. Пожалуйста, см. Обновление 3. –

+0

@tintsi Спасибо, я сделаю редактирование, основанное на этом. –

+0

Кажется, что вторая ссылка создана не в моем коде: ссылка: 1939972532 –

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 

так в основном может быть ошибка на пути вы инстанцировании класс

Смежные вопросы