11

개체 목록을 저장하는 스윙 응용 프로그램이 있습니다. 사용자가 단추를 클릭하면백그라운드 작업 중 스윙 GUI 잠금 방지

목록의 각 개체에 대해 두 가지 작업을 수행 한 다음 완료되면 JPanel에 결과를 그래프로 나타냅니다. 나는 SwingWorker, Callable & Runnable을 시도해 왔지만 목록을 처리하는 동안 (IO 바인드에 따라 몇 분이 걸릴 수 있음) GUI는 잠겨 있습니다.

제가 스레드 또는 무언가를 호출하는 방식 일 가능성이 있거나 그래픽 기능과 관련이있을 수 있다고 생각합니까? 그것은 매우 빠르기 때문에 스레드되지 않습니다.

나는 두 가지 처리 단계를 순서대로 수행해야하므로 두 번째 처리 단계가 첫 번째 단계에서 대기했는지 확인하는 가장 좋은 방법은 무엇입니까? 나는 join()을 사용했다. 그리고 이것을 시도했다. 그러나 이것 역시 내 문제의 원인이 될까 걱정된다.

나는 포인터를 찾기 위해 어디에서나 찾고 있었지만, 내가 찾을 수 없기 때문에 나는 여기서 뭔가 어리석은 짓을하고 있다고 확신한다.

+2

SwingWorker를 사용하는 방법을 나타내는 코드를 포함하면 도움이 될 수 있습니다. –

+0

동의; 우리에게 문제가되는 코드를 보여주십시오. – Rob

답변

18

문제는 오래 실행중인 작업이 GUI 응답 성을 유지하는 스레드를 차단하고 있다는 것입니다.

장기 실행 작업을 다른 스레드에 넣기 만하면됩니다.

타이머를 사용하는 일반적인 방법은 SwingWorker입니다.

Java tutorials에는 이러한 것들을 동시성에 관한 많은 정보가 있습니다.

첫 번째 작업이 두 번째 작업보다 먼저 완료되도록하려면 두 스레드를 같은 스레드에 배치하십시오. 그렇게하면 두 개의 서로 다른 스레드를 올바르게 유지하는 것에 대해 걱정할 필요가 없습니다.

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를 작성하고 시작하도록 지시하기 : 여기

는 SwingWorkerFor 사건의 샘플 구현입니다.

+1

저는 스레드와 SwingWorker에 대해 이미 언급 한 질문에 확신합니다. 또한 SwingUtilities.invokeLater()는 GUI 스레드에서 작업을 실행합니다. – Powerlord

+0

그래, 나는 일반 스윙 스레딩 대답을 준 ... 좀 멍청한 – jjnguy

+0

여기에, 그래, 나는 그 제안을 이미 시도했지만, 올바르게 구현하지 않았을 수도 있습니다 ... 나는 스윙 튜토리얼을 겪었습니다. ,하지만 그다지 스윙 작업자에게는별로 도움이되지 않습니다. 적어도 – Simonw

5

스윙 스레드를 제대로 돌려 보내지 않습니다. 나는 당신이 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.start를 수행하지 않는 대신 run 메소드를 호출 같은데요 직접적으로, 또는 그것을 고정시키는 첫 번째 메소드에서 (thread.join과 같이) 다른 작업을하고있는 경우. 이들 중 어느 것도 스윙 스레드를 해제하지 않습니다. 첫 번째 메서드는 신속하게 반환해야하며 run() 메서드는 원하는만큼 오래 걸릴 수 있습니다.

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

편집 : (실제로 두 번째 편집) 나는 실제로 느끼는 문제에 대해 말하고 싶다. 모델/뷰/컨트롤러 시스템에 관해 더 생각하고 싶을 것이다. 작성중인 코드는 컨트롤러입니다 (보기는 일반적으로 화면의 구성 요소로 간주됩니다 -보기/컨트롤러는 일반적으로 매우 단단합니다).

컨트롤러가 이벤트를 받으면 모델에 작업을 전달해야합니다. 보기가 그림에서 빠져 나옵니다. 모델을 기다리지 않고 방금 완료했습니다.

모델이 완성되면 컨트롤러에 다른 작업을 지시해야합니다. 이것은 invoke 메소드 중 하나를 통해이를 수행합니다. 이것은 컨트롤러로 컨트롤을 다시 전송하고 당신은 즐거운 방법으로 이동합니다. 이런 식으로 생각하면 제어를 분리하고 의도적으로 앞뒤로 전달하는 것은 그렇게 부피가 크지 않으며 실제로 이렇게하는 것이 일반적입니다.

+0

제 경우에는 thread.start() 대신에 thread.run()을하고 있었고 GUI 잠금 장치로 안내해주었습니다. thread.start()를 설정하면 문제가 해결되었습니다. – Alexey

1

GUI 스레드 내부에서 스레드가 끝나기를 기다리고있는 것처럼 들릴 수 있습니다. GUI 스레드는 이러한 스레드에서 기다리지 말고, 대신 작업자 스레드가 플래그를 설정하는 GUI 스레드에서 일부 메소드를 호출하도록해야합니다. 두 플래그가 모두 설정되면 두 스레드가 완료되었음을 알게되고 그래프를 수행 할 수 있습니다.

0

정말 스윙의 스레딩 모델에게 말을 할 수는 없지만 :

을 내가 너무 위해 두 개의 처리 단계를해야 등등 대기 한 두 번째를 확인하는 가장 좋은 방법은 무엇입니까 첫번째?

이런 종류의 기능을 사용하려면 두 개의 작업자 스레드를 만들고 JMS 브로커를 포함시키는 것이 좋습니다. 메시지를 읽은 JMS 대기열로 전달하여 두 스레드로 작업을 전달하십시오. GUI 스레드는 대기열을 검사하여 작업이 언제 발생하는지 확인하고 UI에서 재생 상태를 나타낼 수 있습니다.

0

내 문제의 해결책은 jjnguy와 Bill K의 답변이 섞인 것이므로 매우 감사합니다. 이 모든 작업이 떨어진 GUI에서 작업자 스레드에 의해 수행하고, 또한 SwingWorker의 자체가 모든 작업을 수행되지 않았 음을 보장 받고 확인했다

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(); 
} 

:이 같은 SwingWorker의에서 스레드를 사용하는 데 필요한 이는 문제 일 수 있습니다.

+3

와우 워 워! SwingWorker에서 스레드를 생성하는 이유는 무엇입니까? SwingWorkers (execute() 메소드로 시작한 경우)는 GUI 스레드에서 실행되지 않으므로 여기에 다른 스레드를 작성할 이유가 없어야합니다. –

+0

처음에는 잘못 했음에 틀림 없다. 왜냐하면 그게 나에게 효과가있는 유일한 해결책이기 때문이다. – Simonw