web-dev-qa-db-fra.com

Quelle est la raison possible d'une exception Java.util.concurrent.RejectedExecutionException dans un SingleThreadExecutor?

Je crée l'exécuteur suivant dans un singleton: 

   final private ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
        final ThreadFactory delegate = Executors.defaultThreadFactory();
        public Thread newThread(Runnable paramAnonymousRunnable) { 
            Thread localThread =      this.delegate.newThread(paramAnonymousRunnable);
            localThread.setName("MyTask-" + localThread.getName());
            localThread.setDaemon(XXX.this.daemonThread);
            return localThread;
        }
    });

Et lors de l'exécution du programme, il y a beaucoup d'appels à cette méthode du singleton. Les appels sont effectués dans différents threads et peut-être à la même heure.

private void send(final String paramString) {
  try {
      this.executor.execute(new Runnable() {
          public void run() {
              //DO some interesting stuff
          }
      });
  } catch (Exception localException) {
    this.handler.handle(localException);
  }

}

Et à un moment donné, les piles suivantes commencent à apparaître:

Java.util.concurrent.RejectedExecutionException
        at Java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.Java:1774)
        at Java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.Java:768)
        at Java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.Java:656)
        at Java.util.concurrent.Executors$DelegatedExecutorService.execute(Executors.Java:589)
        at XXXXX.send(XXXX.Java:269)

Pourquoi le JVM lancera une telle exception?

SingleThreadExecutor est soutenu par un LinkedBlockingQueue ().
Et le pool de threads n'a pas été arrêté.

pour information, le jvm est Oracle jdk 1.6. Le singleton est créé avec spring ..__ copy à partir de Java.util.concurrent.Executors:

   public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
       return new FinalizableDelegatedExecutorService
           (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>(),
                                threadFactory));
   }
41
RJO

Il y a deux raisons pour lesquelles execute jette un RejectedExecutionException 

  1. La file d'attente est pleine et vous ne pouvez plus ajouter de threads
  2. Le ThreadPool a été arrêté

Puisque vous utilisez une LinkedBlockingQueue, la seule manière pour que cela se produise est d’arrêter le pool.

54
John Vint

Vous avez peut-être soumis des tâches après avoir appelé executor.shutdown(). Normalement pour arrêter l'exécuteur qu'ils font

    executor.shutdown();
    executor.awaitTermination(10, TimeUnit.MINUTES);
4
Andrey Chaschev

Les threads ne sont pas disponibles pour exécuter la tâche donnée. Aucune file d'attente bloquée liée à la tâche que.

0

Peut-être devriez-vous utiliser un pool de threads au lieu d'utiliser un seul exécutant. 

    executor = new Java.util.concurrent.ThreadPoolExecutor(30, 30, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadFactory() {
        final AtomicInteger threadNumber = new AtomicInteger( 1 );
        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, "Thread No : " + threadNumber.getAndIncrement());
        }
    });
0
cgon