내가 제어 할 수없는 레거시 라이브러리와 통합하고 있습니다.
다음 인터페이스가 정의되어 있습니다.
interface Factory {
Future<Void> subscribe(Context c);
}
이 "구독"메서드는 다른 스레드에서 자주 호출됩니다. "Future.get ()"의 결과에 관심이있는 유일한 상황은 실패한 경우이므로 예외를 가져 와서 처리 할 수 있습니다. 이것은 호출 스레드에서 발생할 필요가 없습니다. 또한 "Future.get ()"에 대한 호출 스레드를 차단하는 것은 제 경우에는 비용이 많이들 수 있습니다. 성공하더라도 전체를 채우는 데 몇 초가 걸릴 수 있습니다.
그래서 내 임무는 실패한 미래를 걸러 내면서이 모든 미래를 어떻게 든 "사후 처리"하는 것입니다. 기본적으로 두 가지 가능한 접근 방식을 볼 수 있습니다.
접근법 # 1 :
Future의 인스턴스를 얻을 때 필요한 작업을 수행 할 별도의 Runnable을 외부 실행자에게 제출합니다.
executor.submit(
new Runnable(){
@Override
public void run() {
try {
future.get();
} catch(Exception e){
// process the exception
}
}
}
);
이 접근 방식의 단점은 잠재적으로 오랫동안 스레드를 차단한다는 것입니다. 그리고 내가 말했듯이이 코드 조각은 다소 자주 실행될 것입니다.
접근법 # 2 :
Future의 인스턴스를 얻을 때 일부 컬렉션에 배치하고 처리를 수행하는이 컬렉션의 요소를 주기적으로 실행하는 별도의 단일 스레드를 지정합니다.
while(true){
Iterator<Future<Void>> iterator = collection.iterator();
while(iterator.hasNext()){
Future<Void> future = iterator.next();
if(future.isDone()){
try {
future.get();
} catch(Exception e){
// process the exception
} finally {
iterator.remove();
}
}
}
TimeUnit.MILLISECONDS.sleep(1000); // sleep
}
어떻게 생각해? 문제를 해결하는 더 좋은 방법이 있습니까?
Future
최고의 옵션을 만들 수있는 손이 없기 때문에 Future
사용자 지정을 사용하여 자체 에서 처리를 트리거합니다 Future
.
따라서 귀하의 경우에는 두 가지 옵션이 혼합 된 것처럼 보일 수있는 패턴을 권장합니다. Future
s를 (스레드 안전) 대기열에 추가하고 s를 Runnable
루프의 모든 항목을 처리하는 실행기에 제출 합니다. 따라서를 구성하여 스레드 수를 제한 할 수 있습니다 Executor
. 즉, Future
s 만큼 스레드가 없지만 여전히 둘 이상의 스레드를 가질 수 있으며 이러한 사후 처리 스레드를 항상 유지하지 않아도됩니다.
완료되지 않은 항목을 다시 대기열에 넣을 때 무한 루프를 방지하려면 로컬 컬렉션을 사용하여 대기중인 항목과 다시 대기열에있는 항목을 구분합니다.
static BlockingQueue<Future<?>> PENDING = …;
static int MAX_ITEMS_PER_JOB = …;
…
/*scheduling code …*/new Runnable() {
public void run()
{
ArrayList<Future<?>> myLocalItems=new ArrayList<>();
PENDING.drainTo(myLocalItems, MAX_ITEMS_PER_JOB);
for(Future<?> f:myLocalItems) {
if(!f.isDone()) PENDING.offer(f); // re-queue
try {
f.get();
} catch(ExecutionException ex) {
handleException(ex.getCause());
}
}
}
};
따라서 Runnable
제한된 수의 Future
s 를 확인하고 처리 한 다음 반환하므로 많은 항목이 보류중인 경우 병렬 처리를 수행하기 위해 여러 번 제출하는 것이 적합하지만 작업이 중단되지 않으므로 더 적은 수의 보류중인 경우에는 해를 끼치 지 않습니다. 할 일이 없다면. 그들은 심지어 적합한 scheduleWithFixedDelay
사용 a ScheduledExecutorService
.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다