只需了解SwingWorker
并提出问题
(我已经搜索了这个答案,但没有具体说明这个设置)
我正在创建一个小型服务器,它最多只能同时连接2-3个连接
我正在使用具有内部类Jframe
SwingWorker
在SwingWorker doInBackground()
中我有:
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);
}
Connection
是runnable
,并在SwingWorker
中声明为子类。
在runnable
完成之前,在SQL中写入一个条目
那么在它死之前这个可运行的怎么能发送一个单挑到Jframe
事件派遣线程
并且Jframe
将检查SQL以获取新条目并将其显示给用户。
最好做什么:
1 - 创建一个界面,所有runnable都可以向Jframe
事件派发线程发送消息。
2 - 对SwingWorker
使用runnables
个Done()
用于所有新连接,并SwingWorker
调用服务器Jframe
中使用{EventQueue.invokeLater..
调用方法的方法{1}}
3 - 或使用PropertyChangeListener(某种程度上不确定)
4 - 让每个runnables都参考Jframe
并执行EventQueue.invokeLater..
答案 0 :(得分:1)
我会选择以下内容:在父线程中有一个线程安全阻塞队列或列表,它将传递给工作线程。任务完成后,工作线程会将包含结果条目ID的消息发布到此阻塞队列中。父线程将阻塞队列,等待子线程的结果。只要队列中有一个元素,父线程就会接受它并从DB获取该数据并将其显示给用户。
答案 1 :(得分:1)
SwingWorker
文档很清楚。您应该继承SwingWorker
并在doInBackground()
方法中执行长任务。您应该使用done()
方法更新用户界面。
真的很容易。
修改强>
使它更清楚。假设您的Connection
类扩展SwingWorker
, 需要实现Runnable
而 需要显式提供线程池运行工作人员。只需将run()
方法的内容放在doInBackground()
。
现在你的主循环看起来像这样;
while (true) {
Socket client_socket = listen_socket.accept();
Connection con = new Connection(client_socket, "name");
con.execute();
}
您似乎在主循环中提交ExecutorService
。是否有特定原因(请注意SwingWorker
为工作线程管理自己的内部ThreadPoolExecutor
。它是否限制并发客户端的数量?如果是这样,还有其他方法可以实现这一目标。
答案 2 :(得分:1)
我尝试创建一个生成后台工作线程的SwingWorker示例,其结果通过固定池ExecutorService和CompletionService发布。我仍然有一些关于在一个线程内创建工作线程的线程安全性的问题,然后在另一个线程(SwingWorker后台线程)内部调用get的未来。
例如:
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();
}
});
}
}
最受欢迎的更正!