2010-02-06 3 views
2

(아래 편집을 읽으십시오.이 질문은 분명히 혼란 스럽습니다.)자바 : 거기 SwingUtilities.invokeNowOrLaterIfEDT (...) 또는 이와 유사합니까?

다음은 일반적인 SwingUtilities.invokeLater 호출입니다.

 SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
     ... 
    } 
    }); 

이제는 SwingUtilities.invokeNowOrLaterIfEDT.

물론

그러나 이것은 EDT에서 호출 될 때마다 새로운 스레드를 만드는 단점이 있습니다. (그리고 새로운 스레드를 기다릴 필요가 없습니다. 예정대로).

Runnables을 대기열에 넣기 위해 일부 차단 대기열을 사용하여 응용 프로그램 수명주기 동안 실행중인 추가 스레드 (지연 생성이 가능)를 실행하는 또 다른 방법이 있습니다. 이점은 EDT와 같은 메서드를 호출 할 때마다 스레드가 끊임없이 생성되지 않는다는 것입니다.

기본 Java API에는 이와 비슷한 것이 있습니까?

위의 예와 같이 EDT에서 호출 할 때마다 새로운 스레드를 작성하거나 EDT 외부에서 실행될 Runnables가 대기열에 추가되거나 다른 스레드가있을 때마다 새 스레드를 작성하면됩니까?

EDIT : SwingUtilities.invokeLater가 EDT에서 호출되었거나 호출되지 않았을 수 있음을 염두에두고 있던 방법이 EDT에서 호출되었거나 호출되지 않았을 수 있습니다. GUI/EDT에서 사용자 조치로 인해 트리거 될 수도 있고 트리거되지 않을 수도있는 완전히 비동기적인 것을 실행하는 것입니다. 제 생각에 SwingUtilities.invokeLater은 EDT에 있거나 EDT에있을 때 호출 할 때 신경 쓰지 않고 EDT에서 무언가를 실행할 수 있다는 점에서 매우 편리하다고 생각합니다. 그리고 제가 위에 보여준 invokeNowOrLaterIfEDT(...)은 매우 편리하다고 생각합니다. 그러나 나는 그것에 착각 할 수도 있습니다. 그런 방법에 대한 필요성이 미쳤습니까? 이제 나는 의심하기 시작했다!?

EDIT TWO : 전혀 명확하지 않았고 깨닫습니다. 죄송합니다. EDT가 아닌 비동기로 실행하려는 작업은 매우 긴 프로세스가 아니며 진행률 표시 줄이나 진행 상황을 보여주는 것과 같은 업데이트가 필요하지 않습니다. 그것은 또한 단일 스레드/대기열 (분명히, 내가 질문에 명시된 경우) 문제가 아니에요. 나는 스레드 풀 (thread pool) 이후에 효율적으로 다양한 코어에 부하를 분산시키는 것이 아닙니다. 이것은 단지 EDT에서 실행될 필요가없고 EDT에서 호출 될 수있는 작은 계산이기 때문입니다. EDT 외부에서 실행하고 싶은 작은 비동기식 기능입니다.

하지만 지금은 답을 통해 단일 스레드와 Runnable 큐를 사용하여 구현 된 것이라면 긴 계산을위한 그런 유틸리티 메소드를 호출함으로써 발에서 총을 쏘아내는 것은 매우 쉽다.

+0

이게 당신이 원하는 것입니다. invokeNowOrLaterIfEDT에 전달 된 실행 파일이 EDT –

+0

에서 실행되지 않으므로 달성하고자하는 목적이 무엇인지, 어쩌면 우리는 대안을 제공 할 수 있습니다. 그리고 Java는 그런 API를 제공하지 않습니다. –

+1

@Suraj : 달성하고자하는 것은 분명히 질문에 명시되어 있습니다. 목표는 EDT가 아닌 스레드에서 실행하는 것입니다. 당신이 알아 차렸 듯이, EDT에서 결코 뛰지 않기 위해서입니다. – SyntaxT3rr0r

답변

3
  1. 어떤 경우 든 메소드의 실행 가능 파일이 절대로 EDT에서 실행되지 않기 때문에 정말로 수행하고 싶은 것이 확실합니까?
  2. 이제는이 메서드를 호출 할 수있는 빈도와 빈도에 대해 숙지 해주십시오. ThreadPool을 사용해야한다고 생각합니다. 동시 패키지에서 ThreadPoolExecutor 및 기타 API를 사용하는 것이 좋습니다.

ThreadPoolExecutor 및 Executors와 같은 java.util.concurrent API를 사용하는 장점 중 하나는 직접 API를 호출하고 추가 작업을하지 않아도 많은 매개 변수와 전체 풀링 시스템을 미세 조정할 수 있다는 것입니다.

+0

@Suraj : 오, 나는 내 질문에 명확하지 않았습니다 ... 왜 당신과 애쉬가 이런 종류의 대답을 준지 이해합니다. 문제. – SyntaxT3rr0r

2

또 다른 옵션 (Suraj's 외에도)은 SwingWorker을 사용하는 것입니다.

이 수업은 당신이하기를 원하는 목적으로 특별히 설계되었습니다 : EDT에서 (아마도 장기 실행) 과정을 가져 와서 별도의 스레드에서 실행하십시오. SwingWorker은 모든 스레드 컨텍스트 스위치를 처리 할 수있는 이점이 있으며, 스레드 스레딩에 대해 걱정할 필요없이 EDT에 다시 업데이트 (예 : 진행률 표시 줄 표시)를 제공 할 수 있습니다.

2

"모든 비동기 호출에 대해 새 스레드를 만들거나 전용 스레드/스레드 풀을 사용하는 것이 더 낫습니까?"라는 질문에 답하는 것 같습니다.

불행히도, 나는 대답이 "그것이 달렸어"라고 생각합니다. 이러한 작업이 짧고 드문 경우, 새 스레드가 잘 될 것입니다. 서로 긴 블로킹을 막을 걱정이 있다면 아마 스레드 풀이 필요합니다.

static ExecutorService ex = Executors.newCachedThreadPool(); 

public static void invokeOutsideEDT(Runnable r) { 
    if (SwingUtilities.isEventDispatchThread()) { 
     ex.submit(r); 
    } else { 
     r.run(); 
    } 
} 

As Suraj noted

concurrent 패키지는 여기에 당신에게 기성 많은 선택을 제공합니다. Executors.newCachedThreadPool() 나는 위에 쓰인 스레드를 사용하여 필요에 따라 스레드를 추가하고 오래된 스레드를 재사용합니다. 그러나 대신 Executors.newSingleThreadExecutor()을 시도하여 장기 실행 작업이 실제로 문제가되는지 확인하거나 Executors.newFixedThreadPool()에 설정된 수의 스레드를 사용하여 n 동시 작업 중 일부가 장기 실행 일지라도 항상 처리 할 수 ​​있는지 확인하십시오.