development

RejectedExecutionException의 원인은 무엇입니까?

big-blog 2020. 12. 5. 10:10
반응형

RejectedExecutionException의 원인은 무엇입니까?


내 바람둥이 서버 (+ liferay)에서이 예외가 발생합니다.

java.util.concurrent.RejectedExecutionException

내 수업은 다음과 같습니다.

public class SingleExecutor extends ThreadPoolExecutor {
  public SingleExecutor(){
    super(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
  }

  @Override
  public void execute(Runnable command) {
    if(command instanceof AccessLogInsert){
        AccessLogInsert ali = (AccessLogInsert)command;
        ali.setConn(conn);
        ali.setPs(ps);
    }
    super.execute(command);
  }
}

줄에이 예외가 표시됩니다. super.execute(command);이 오류는 대기열이 꽉 찼지만 LinkedBlockingQueue크기가 2 ^ 31 일 때 발생할 수 있으며 대기중인 명령이 너무 많지 않다고 확신합니다.

처음에는 모든 것이 안정적이지만 전쟁을 재배치하면 전쟁이 시작됩니다. 이 클래스는 전쟁의 일부가 아니라 tomcat / lib의 항아리에 있습니다.

왜 이런 일이 발생했고 어떻게 해결해야하는지 아십니까?


에서 가능한 ThreadPoolExecutor의 JavaDoc을

메서드에 제출 된 새 작업 은이 종료 될 때 와 최대 스레드 및 작업 대기열 용량 모두에 대해 유한 경계를 사용하고 포화 상태 일 execute(java.lang.Runnable)때 거부됩니다 . 두 경우 모두 execute 메서드는 해당 . 4 개의 사전 정의 된 핸들러 정책이 제공됩니다.ExecutorExecutorRejectedExecutionHandler.rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor)RejectedExecutionHandler

  1. 기본값 ThreadPoolExecutor.AbortPolicy에서 핸들러는 RejectedExecutionException거부 시 런타임 을 발생시킵니다.
  2. 에서 ThreadPoolExecutor.CallerRunsPolicy실행을 호출하는 스레드는 작업을 실행합니다. 이것은 새로운 작업이 제출되는 속도를 늦추는 간단한 피드백 제어 메커니즘을 제공합니다.
  3. 에서는 ThreadPoolExecutor.DiscardPolicy실행할 수없는 작업이 삭제됩니다.
  4. 에서 ThreadPoolExecutor.DiscardOldestPolicy집행자가 종료되지 않은 경우, 작업 큐의 선두에있는 태스크가 삭제되어 실행이 시도됩니다 (이 반복되는 원인이 다시 실패 할 수있다.)

다른 종류의 RejectedExecutionHandler클래스 를 정의하고 사용할 수 있습니다. 이렇게하려면 특히 정책이 특정 용량 또는 대기열 정책에서만 작동하도록 설계된 경우주의가 필요합니다.

따라서 아마도 전쟁을 다시로드하면 Executor. 관련 라이브러리를 전쟁에 투입하여 Tomcat이 ClassLoader앱을 올바르게 다시로드 할 수있는 가능성을 높이십시오.


OrangeDog의 훌륭한 답변에 추가하기 위해 an의 계약 Executor은 실제로 실행자가 포화 상태 일 때 (즉, 대기열에 공간이 없음) execute메서드가 RejectedExecutionException발생하도록 하는 것 입니다.

그러나 대신 차단 하면 새 작업을위한 대기열에 공간이 생길 때까지 자동으로 대기 하는 것이 유용했을 것 입니다.

다음 사용자 정의를 사용하면이 BlockingQueue를 달성 할 수 있습니다.

public final class ThreadPoolQueue extends ArrayBlockingQueue<Runnable> {

    public ThreadPoolQueue(int capacity) {
        super(capacity);
    }

    @Override
    public boolean offer(Runnable e) {
        try {
            put(e);
        } catch (InterruptedException e1) {
            return false;
        }
        return true;
    }

}

이는 본질적으로 역압 알고리즘을 구현하여 실행기가 포화 될 때마다 생산자를 느리게합니다.

다음과 같이 사용하십시오.

int n = Runtime.getRuntime().availableProcessors();
ThreadPoolExecutor executor = new ThreadPoolExecutor(0, n, 1, TimeUnit.MINUTES, new ThreadPoolQueue(n));
for (Runnable task : tasks) {
    executor.execute(task); // will never throw, nor will queue more than n tasks
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.HOURS);

참고 URL : https://stackoverflow.com/questions/8183205/what-could-be-the-cause-of-rejectedexecutionexception

반응형