문제

객체 목록을 저장하는 스윙 애플리케이션이 있습니다. 사용자가 버튼을 클릭하면

목록의 각 객체에서 두 개의 작업을 수행하고 완료되면 결과를 JPANEL로 그래프로 표시합니다. 나는 스윙 워크 인, 호출 가능 및 런닝 가능한 처리를 시도했지만, 내가 무엇을하든 목록을 처리하는 동안 (IO 바운드로 몇 분이 걸릴 수 있음) GUI는 잠겨 있습니다.

아마도 내가 스레드 나 무언가를 부르는 방식이라고 생각하거나 그래프 기능과 관련이 있을까요? 그것은 매우 빠르기 때문에 스레드되지 않습니다.

두 개의 처리 단계도 순서대로해야합니다. 두 번째 처리 단계가 첫 번째로 기다렸는지 확인하는 가장 좋은 방법은 무엇입니까? 나는 join ()을 사용한 다음 사용했습니다

while(x.isAlive())  
{  
        Thread.sleep(1000);  
}

이것을 시도하고 보장하기 위해서는 이것이 내 문제의 원인이 될 수 있다고 걱정합니다.

나는 약간의 포인터를 찾고 있었지만, 나는 찾을 수 없기 때문에 여기서 바보 같은 일을하고 있다고 확신합니다.

도움이 되었습니까?

해결책

문제는 장기 실행 작업이 GUI 응답을 유지하는 스레드를 차단하는 것입니다.

당신이해야 할 일은 다른 스레드에 장기적인 작업을하는 것입니다.

이 작업을 수행하는 몇 가지 일반적인 방법은 타이머를 사용하는 것입니다. SwingWorker.

그만큼 자바 튜토리얼 동시성 교훈에 이러한 것들에 관한 많은 정보가 있습니다.

첫 번째 작업이 두 번째 작업 전에 완료되도록하려면 동일한 스레드에 둘 다 넣으십시오. 그렇게하면 두 개의 다른 스레드를 올바르게 유지하는 것에 대해 걱정할 필요가 없습니다.

다음은 귀하의 사례에 대한 스윙 워크 워커의 샘플 구현입니다.

public class YourTaskSwingWorkerSwingWorker extends SwingWorker<List<Object>, Void> {
    private List<Object> list
    public YourClassSwingWorker(List<Object> theOriginalList){
        list = theOriginalList;
    }

    @Override
    public List<Object> doInBackground() {
        // Do the first opperation on the list
        // Do the second opperation on the list

        return list;
    }

    @Override
    public void done() {
        // Update the GUI with the updated list.
    }
}

이 코드를 사용하려면 목록을 수정하기위한 이벤트가 해고되면 새로 작성하십시오. SwingWorker 시작하라고 말하십시오.

다른 팁

스윙 스레드를 올바르게 반환하지 않습니다. 나는 당신이 Callable/Runnable을 사용하고 있다는 것을 알고 있지만 당신이 제대로하지 않는다고 생각합니다 (확실히 알기 위해 충분한 코드를 게시하지는 않았지만).

기본 구조는 다음과 같습니다.

swingMethod() { // Okay, this is a button callback, we now own the swing thread
    Thread t=new Thread(new ActuallyDoStuff());
    t.start();
}

public class ActuallyDoStuff() implements Runnable {
    public void run() {
        // this is where you actually do the work
    }
}

이것은 내 머리 꼭대기에서 벗어나지 만 스레드를 사용하지 않고 대신 실행 메소드를 직접 호출하거나 첫 번째 방법에서 그것을 잠그는 다른 작업을 수행하고 있다고 생각합니다. Thread.join처럼). 이들 중 어느 것도 스윙 스레드를 자유롭게하지 않을 것입니다. 첫 번째 메소드는 빠르게 반환해야합니다. Run () 메소드는 원하는만큼 오래 걸릴 수 있습니다.

첫 번째 메소드에서 thread.join을 수행하는 경우 스레드가 시스템으로 반환되지 않습니다!

편집 : (실제로 두 번째 편집) 나는 당신이 실제로 느끼고있는 문제에 대해 말하기 위해 생각합니다. 모델/뷰/컨트롤러 시스템 측면에서 더 많은 생각을하고 싶을 수도 있습니다. 당신이 쓰는 코드는 컨트롤러입니다 (보기는 일반적으로 화면의 구성 요소로 간주됩니다. view/컨트롤러는 일반적으로 매우 단단히 바인딩됩니다).

컨트롤러가 이벤트를 받으면 작업을 모델로 전달해야합니다. 그런 다음보기가 그림에서 벗어납니다. 모델을 기다리지 않고 방금 완료되었습니다.

모델이 완료되면 컨트롤러에 다른 작업을하도록 지시해야합니다. 호출 방법 중 하나를 통해이를 수행합니다. 이것은 컨트롤을 컨트롤러로 전송하고 당신은 당신의 즐거운 길을 계속합니다. 당신이 이런 식으로 생각한다면, 제어를 분리하고 의도적으로 그것을 앞뒤로 전달하는 것은 그렇게 부피가 큰 느낌이 들지 않으며, 실제로 이런 식으로 그렇게하는 것이 매우 일반적입니다.

문제는 GUI 스레드 내부에서 스레드를 기다리고 있다는 것 같습니다. GUI 스레드는 이러한 스레드를 기다리지 말고 대신 작업자 스레드가 GUI 스레드에서 플래그를 설정하는 메소드를 호출해야합니다. 두 플래그가 모두 설정되면 두 스레드가 완료되어 그래프를 수행 할 수 있습니다.

스윙 스레딩 모델과 실제로 말할 수는 없지만 :

두 개의 처리 단계도 순서대로해야합니다. 두 번째 처리 단계가 첫 번째로 기다렸는지 확인하는 가장 좋은 방법은 무엇입니까?

이런 종류의 기능을 위해 두 개의 작업자 스레드를 만들고 JMS 브로커를 포함하는 것이 좋습니다. 메시지를 읽은 JMS 대기열에 전달하여 두 스레드에 작업을 전달하십시오. GUI 스레드는 대기열을 자유롭게 검사하여 작업이 발생하는시기를 결정하고 UI의 플레이 상태를 나타냅니다.

내 문제에 대한 해결책은 Jjnguy와 Bill K의 답변이 혼합되어 있었으므로 그 사람들에게 대단히 감사합니다. 나는 다음과 같은 스윙 워크 내에서 스레드를 사용해야했습니다.

public class Worker extends SwingWorker<Void, Void>   
{  
    private List<Object> list;  
    public YourClassSwingWorker(List<Object> theOriginalList){  
        list = theOriginalList;  
    }

    @Override
    public List<Object> doInBackground() {
        Thread t = new Thread(new ProcessorThread(list));  
        t.start();
    }

    @Override
    public void done() {
        // draw graph on GUI
    }
}  
class ProcessorThread implements Runnable {  
    //do lots of IO stuff  
    Thread t2 = new Thread(new SecondProcess());
    t2.start();  
}

이로 인해 모든 작업이 GUI에서 멀리 떨어진 작업자 스레드에 의해 수행되었으며 Swingworker 자체가 모든 작업을 수행하지 않도록했습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top