2016-06-22 3 views
1

У меня есть код, который помещает некоторые данные в блокирующую очередь и отправляет потоковые задачи службе Java-исполнителя на основе фиксированного пула потоков. Когда я пытаюсь выключить исполнителя, хотя он не выключается, любая идея, пожалуйста?Java-исполнитель никогда не выключается?

import java.util.concurrent.ArrayBlockingQueue; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.TimeUnit; 

public class ThreadExecutir { 
    public static ArrayBlockingQueue<String> files; 

    public static void main(String[] args) { 
     // TODO Auto-generated method stub 
     shutdownExec(); 
    } 

    private static void shutdownExec() { 
     int size = 10; 
     files = new ArrayBlockingQueue<String>(100); 
     for (int i = 0; i < 5; i++) { 
      files.add("Java " + i); 
     } 

     ThreadExecutir outer = new ThreadExecutir(); 
     ExecutorService executor = Executors.newFixedThreadPool(size); 
     for (int i = 0; i < 3 * size; i++) { 
      executor.submit(outer.new myThread()); 
     } 
     System.out.println(executor.isShutdown()); 
     executor.shutdown(); 

     try { 
      executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); 
      System.out.println("Awaiting for threads to complete!"); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     if (files.isEmpty()) 
      executor.shutdownNow(); 
     System.out.println(executor.isShutdown()); 

    } 

    class myThread extends Thread { 
     public void run() { 

      String threadName = Thread.currentThread().getName(); 
      System.out.println("Thread " + threadName + "started running! "); 
      try { 
       String uploadThis = files.take(); 
       System.out.println("I'm working " + threadName + " " 
         + uploadThis); 
       // this.sleep(1000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } finally { 
       System.out.println("Thread " + threadName 
         + " finished running! "); 
      } 
     } 
    } 
} 

ответ

4

После нескольких myThread случаев потреблял все элементы files, остальное блок на files.take().

Javadoc из shutdown заявляет

Инициирует процедуру завершения работы, в которых ранее представленные задачи выполняется, но никакие новые задачи не будут приняты. Invocation не имеет никакого дополнительного эффекта, если он уже выключен.

Вы отправили все свои 30 заданий (10 из которых выполняются), прежде чем звонить shutdown. Поэтому все они должны закончить выполнение до того, как ExecutorService можно считать завершенным. Но большинство из них не могут закончить выполнение, поскольку на данный момент ничего не существует, чтобы заставить их остановить блокировку на take().

Вам необходимо либо отправить больше предметов на ArrayBlockingQueue, либо прервать потоки в ExecutorService. shutdownNow может использоваться для прерывания этих потоков.

Обратите внимание, что прерывания могут быть недостаточно, чтобы остановить ваши потоки, так как прерывание может появиться перед блокирующим вызовом. Вам понадобится больше sophisticated solution, like a poison pill.


Хотя вы подклассы Thread,

class myThread extends Thread { 

вы используете только myThread как Runnable (Thread орудий Runnable). Это довольно бессмысленно. Только осуществить Runnable

class myThread implements Runnable { 
+0

Я добавил ядовитую таблетку в очередь, но нити все еще не умирают сами! Есть идеи? –

1

Вы отправили только 5 строк в очередь и 30 заданий. Первые 5 задач потребляют все 5 строк от files, а следующая блокируется, пытаясь вызывать poll() строку из пустой очереди (notEmpty.await() вызывается в очереди).

Тема будет ждать, пока она не будет прервана. Исполнитель будет ждать завершения своих потоков.

Поэтому код будет застрял на executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS) и никогда не достигает if (files.isEmpty()) executor.shutdownNow();

Похоже, вы должны использовать files.poll() вместо files.take() - это не запирается в пустой очереди return (count == 0) ? null : dequeue();.

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