2012-06-22 1 views

답변

1

여기에 몇 가지 생각에서 큐 -
PriorityBlockingQueue을 ArrayBlockingQueue 등을 사용하고 있지? 나에게 필요한 것 같은데. 우선 모든 요소를 ​​동등한 우선 순위로 설정하십시오.
예외가 발생하는 경우 더 높은 우선 순위의 대기열에 다시 삽입하십시오.

+0

하지만 두 번째 시간이 아닌 한 번만 다시 시도하고 싶습니다. – Maverick

+0

은 Executor 's의 rejecion 핸들러로이를 수행 할 수있는 코드를 보여줄 수 있습니다. – Maverick

+0

Als, 거부하면 다시 실행해야합니다. 그러나 그것이 다시 실패한다면, 그것은 그것을 거절해야합니다. – Maverick

0

가장 간단한 것이 우선 순위 대기열 일 수 있습니다. 작업에 재시도 번호를 붙이십시오. 0으로 시작합니다. 실패한 실행 후에는 모든 것을 버리고 0을 증가시키고 높은 우선 순위로 다시 대기열에 넣습니다. 이 방법을 사용하면 나중에 3 번 이상 실행하도록 쉽게 결정할 수 있습니다. 아래쪽은 작업 클래스를 수정해야한다는 것입니다.

다른 아이디어는 비 차단, 스레드 안전, 높은 우선 순위 큐를 설정하는 것입니다. 새로운 작업을 찾을 때 먼저 비 차단 대기열을 확인하고 거기에있는 것을 실행하십시오. 그렇지 않으면 차단 대기열로 이동하십시오. 이는 현재의 상태에서 작동 할 수 있으며, 지금까지는 가장 간단한 솔루션입니다. 문제는 스케줄러가 차단 대기열에서 차단되는 동안 높은 우선 순위 대기열이 가득 찰 수 있다는 것입니다.

이 문제를 해결하려면 사용자가 직접 차단해야합니다. 두 대기열은 모두 비 블로킹이어야합니다. (제안 : java.util.concurrent.ConcurrentLinkedQueue.) 결과가없는 두 대기열을 모두 폴링 한 후 wait()을 모니터에 표시합니다. 어떤 것이 대기열에있을 때 notifyAll()을 호출해야 스케줄러가 다시 시작될 수 있습니다. 스케줄러가 두 대기열을 모두 점검 한 후, 그러나 wait()을 호출하기 전에 통지가 발생하지 않도록 세심한주의가 필요합니다.

추 설명서 블로킹 제 솔루션

프로토 번호. 일부 스레딩이 제안되지만 독자는 자신의 상황을 가장 잘 알 수 있습니다. 어떤 코드가 잠금을 기다리는 것을 막기 쉽고, 광범위한 작업을하면서 스레드 (및 코어)를 몇 분 동안 묶어두기 쉽고, 다른 코드가 모두 끝날 때까지 기다릴 필요가 없다. 깊이 생각한. 예를 들어 실패한 실행이 동일한 스레드에서 즉시 재실행 할 수 있으면 시간이 많이 소요되는 정리가 필요하지 않으므로이 코드의 대부분은 쓸모 없게 될 수 있습니다.

private final ConcurrentLinkedQueue mainQueue = new ConcurrentLinkedQueue(); 
private final ConcurrentLinkedQueue prioQueue = new ConcurrentLinkedQueue(); 
private final Object entryWatch = new Object(); 

/** Adds a new job to the queue. */ 
public void addjob(Runnable runjob) { 
    synchronized (entryWatch) { entryWatch.notifyAll(); } 
} 
/** The endless loop that does the work. */ 
public void schedule() { 
    for (;;) { 
     Runnable run = getOne(); // Avoids lock if successful. 
     if (run == null) { 
      // Both queues are empty. 
      synchronized (entryWatch) { 
       // Need to check again. Someone might have added and notifiedAll 
       // since last check. From this point until, wait, we can be sure 
       // entryWatch is not notified. 
       run = getOne(); 
       if (run == null) { 
        // Both queues are REALLY empty. 
        try { entryWatch.wait(); } 
        catch (InterruptedException ie) {} 
       } 
      } 
     } 
     runit(run); 
    } 
} 
/** Helper method for the endless loop. */ 
private Runnable getOne() { 
    Runnable run = (Runnable) prioQueue.poll(); 
    if (run != null) return run; 
    return (Runnable) mainQueue.poll(); 
} 
/** Runs a new job. */ 
public void runit(final Runnable runjob) { 
    // Do everthing in another thread. (Optional) 
    new Thread() { 
     @Override public void run() { 
      // Run run. (Possibly in own thread?) 
      // (Perhaps best in thread from a thread pool.) 
      runjob.run(); 
      // Handle failure (runit only, NOT in runitLast). 
      // Defining "failure" left as exercise for reader. 
      if (failure) { 
       // Put code here to handle failure. 
       // Put back in queue. 
       prioQueue.add(runjob); 
       synchronized (entryWatch) { entryWatch.notifyAll(); } 
      } 
     } 
    }.start(); 
} 
/** Reruns a job. */ 
public void runitLast(final Runnable runjob) { 
    // Same code as "runit", but don't put "runjob" in "prioQueue" on failure. 
} 
+0

동일한 프로토 타입 코드를 표시 할 수 있습니까? – Maverick

+0

@Maverick : 두 개의 비 블로킹 큐가있는 세 번째 아이디어입니까? – RalphChapin

+0

@Maverick 당신이 그랬다면, 추가를 참조하십시오. 당신이하지 않았다면 추가는 아마도 도움이 될 것입니다. – RalphChapin