2011-11-24 2 views
4

그냥 SwingWorker을 learnd과 질문이
(나는이 만에 대답 검색이 아닌 구체적으로이 설정을 해결)자바 SwingWorker의 통지 이벤트 발송 쓰레드

임은을 만들 최소 2-3 개의 연결 만 가능합니다.
임 SwingWorker의 doInBackground()에서 내부 클래스 SwingWorker

을 가지고 Jframe을 사용하여 내가 가지고 :

while(true) { 
    Socket client_socket = listen_socket.accept(); 
    Connection con = new Connection(client_socket, "name"); 
    Future<Connection> future = es.submit(con , con); 
    tasks.add(future); 
} 

ConnectionrunnableSwingWorker의 하위 클래스로 선언된다.

runnable이 완료되기 전에 SQL에 항목을 작성하십시오.
어떻게하면이 실행 가능 여부가 종료되기 전에 Jframe 이벤트 발송 스레드로 헤드 업을 보낼 수 있습니다.
Jframe은 SQL에서 새 항목을 확인하여 사용자에게 표시합니다.

할 무엇이 최선인지 :

1 - 모든 실행 가능한이 Jframe 이벤트 디스패치 스레드에 메시지를 보낼 수있는 인터페이스 마녀를 만들 수 있습니다.

2 - SwingWorker 모든 새 연결 runnables의 insted 사용 Done() 전화 사용하여 서버 Jframe에서 메소드를 호출 SwingWorker의 방법 EventQueue.invokeLater..

3가 - 나 (어떻게 든 더 확인) PropertyChangeListener를 사용

4 - 각각의 runnables가 Jframe을 참조하도록하고 EventQueue.invokeLater..

답변

1

SwingWorker 문서는 매우 명확합니다. SwingWorker을 서브 클래스 화하고 doInBackground() 메소드에서 긴 태스크를 수행해야합니다. done() 방법으로 UI를 업데이트해야합니다.

정말 쉽습니다.

편집 :
분명하게 말하십시오. 당신의 Connection 클래스를 가정하는 것은 Runnable를 구현할 필요가 않으며 명시 적으로 노동자를 실행하는 스레드 풀을 제공 할 필요가 없습니다을한다. 그냥 doInBackground()run() 방법의 내용을 넣어 SwingWorker를 확장합니다.

이제 기본 루프가 다음과 같이 표시됩니다.

while (true) { 
    Socket client_socket = listen_socket.accept(); 
    Connection con = new Connection(client_socket, "name"); 
    con.execute(); 
} 

메인 루프의 ExecutorService에 제출하는 것으로 보입니다. 이에 대한 특별한 이유가 있습니까 (SwingWorker은 작업자 스레드에 대해 자체 내부 ThreadPoolExecutor을 관리합니다). 동시 클라이언트 수를 제한합니까? 그렇다면이를 수행 할 수있는 다른 방법이 있습니다.

+0

내 서버 SwingWorker가 서버 종료시 'done()'을 사용하고 있습니다. 'doInBackground()'에서 시작한 모든 'runnables'에 대해서는 'done()'메커니즘이 없습니다. – Erik

+1

저는 SwingWorker 사용에 대해 이미 알고 있다고 생각합니다. 그의 문제는 SwingWorker 사용의 기본을 넘어서 한 단계입니다. –

+1

@ Erik : 그들은 Runnables입니까, 아니면 미래입니까? 후자의 경우, 그들은 FutureTask 또는 이와 유사한 어떤 종류의 완료 메소드를 가지고 있습니다. –

1

나는 다음과 같이 갈 것입니다 : thread safe blocking queue 또는 list를 가지고 있습니다. 부모 스레드는 작업자 스레드로 전달됩니다. 작업이 완료되면 작업자 스레드는 결과 항목 ID가 들어있는 메시지를이 차단 대기열에 게시합니다. 부모 스레드는 자식 스레드의 결과를 기다리는 대기열에서 차단됩니다. 대기열에 요소가있을 때마다 상위 스레드가이를 취하여 DB에서 해당 데이터를 가져 와서 사용자에게 표시합니다.

+0

수 있습니다. 내 경우에는 부모가 'SwingWorker'이고 이미 'doInBackground() listen_socket.accept()'에서 차단 중입니다. 차단 대기열 휘발성 목록을 보유하고있는 부모의 청취 스레드를 시작할 수 있으며 EventQueue.invokeLater를 사용하여 'Jframe'에 메시지를 게시합니다. 임 전문가가 아니며 과도한 느낌이 – Erik

+0

입니다. 저는 개인적으로 대형 분산 시스템에서이 프로듀서/소비자를 사용하며 지금까지 아무런 문제가 없었습니다 – GETah

1

배경 작업자 스레드를 생성하는 SwingWorker 예제를 만들려고했습니다. 그 결과는 고정 풀 ExecutorService와 CompletionService를 통해 게시됩니다. 한 스레드 안에 작업 스레드를 작성하고 다른 스레드 (SwingWorker 백그라운드 스레드) 내부에 미래를 가져 오는 스레드 안전성과 관련하여 몇 가지 질문이 있습니다. 예를 들어

:

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.util.List; 
import java.util.concurrent.Callable; 
import java.util.concurrent.CompletionService; 
import java.util.concurrent.ExecutionException; 
import java.util.concurrent.ExecutorCompletionService; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 

import javax.swing.*; 

@SuppressWarnings("serial") 
public class TestSwingWorker extends JPanel { 
    public static final int POOL_SIZE = 4; 
    private JTextArea tArea = new JTextArea(10, 30); 
    private JButton doItBtn; 

    public TestSwingWorker() { 
     doItBtn = new JButton(new AbstractAction("Do It!") { 
     public void actionPerformed(ActionEvent ae) { 
      swingWorkerRunning(true); 
      MySwingWorker mySW = new MySwingWorker(); 
      mySW.execute(); 
      tArea.append("SwingWorker started\n"); 
     } 
     }); 
     JPanel btnPanel = new JPanel(); 
     btnPanel.add(doItBtn); 
     tArea.setEditable(false); 
     tArea.setFocusable(false); 

     setLayout(new BorderLayout()); 
     add(new JScrollPane(tArea), BorderLayout.CENTER); 
     add(btnPanel, BorderLayout.SOUTH); 
    } 

    private class MySwingWorker extends SwingWorker<String, String> { 
     @Override 
     protected String doInBackground() throws Exception { 
     ExecutorService execService = Executors.newFixedThreadPool(POOL_SIZE); 
     final CompletionService<String> completionService = new ExecutorCompletionService<String>(
       execService); 
     new Thread(new Runnable() { 

      @Override 
      public void run() { 
       for (int i = 0; i < POOL_SIZE; i++) { 
        final int index = i; 
        completionService.submit(new Callable<String>() { 
        public String call() throws Exception { 
         Thread.sleep(2000 * index + 500); 
         return "Callable " + index + " complete"; 
        } 
        }); 
        try { 
        Thread.sleep(1000); 
        } catch (InterruptedException e) { 
        } 
       } 
      } 
     }).start(); 

     for (int i = 0; i < POOL_SIZE; i++) { 
      Future<String> f = completionService.take(); 
      publish(f.get()); 
     } 

     return "Do in background done"; 
     } 

     @Override 
     protected void process(List<String> chunks) { 
     for (String chunk : chunks) { 
      tArea.append(chunk + "\n"); 
     } 
     } 

     @Override 
     protected void done() { 
     try { 
      tArea.append(get() + "\n"); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } catch (ExecutionException e) { 
      e.printStackTrace(); 
     } finally { 
      swingWorkerRunning(false); 
     } 
     } 
    } 

    public void swingWorkerRunning(boolean running) { 
     doItBtn.setEnabled(!running); 
    } 

    private static void createAndShowGui() { 
     TestSwingWorker mainPanel = new TestSwingWorker(); 

     JFrame frame = new JFrame("TestSwingWorker"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

수정 환영!