我正在尝试使用 swing 编写一些客户端/服务器应用程序。 我的线程通信有问题。我不明白如何将一些数据从 EDT 发送回正在运行的线程。
class SwingUI extends JFrame implements IUpdater{
@Override
public void askPermission(String str) {
int i = JOptionPane.showConfirmDialog(this, str);
// (?)Send i back
}
}
class Connection implements Runnable{
IUpdater updater;
Connection(IUpdater u){updater = u;}
@Override
public void run() {
String command = "download_file"; //=getCommand(); from a socket
if(command.equals("download_file")){
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
updater.askPermition(command);
}
});
// (?)wait until user answers
// int answ = getAnswer();
// if answ == OK
System.out.println("Sending_File");
// if answ == DENY
//System.out.println("Denied");
}
}
}
interface IUpdater{
void askPermission(String str);
}
我需要从用户界面获得某种响应。也许不仅仅是 int 值,还有 List 对象。
例如,连接后,我需要在 userForm 中为某些客户端准备一些数据,然后发送它。我该怎么办?
Swingworker 只允许将数据发布到 EDT 或触发 EDT 正在监听的事件,而不允许接收消息。
此外,我还必须以某种方式让正在运行的线程等待。我不确定 sleep(n) 直到某些变量发生变化是一个好主意,但我不知道在这种情况下如何使用监视器,我应该这样做。也许有一些设计模式可以解决它?
我确信这是一种常见情况,但我找不到任何相关信息。
最佳答案
线程只执行 Runnables,它们不能发送/接收消息或值,Runnables 可以做到这一点。但是,您无法从仅接受 String 且不返回任何内容的接口(interface)方法获取值。所以,首先更新界面:
public interface IUpdater {
int askPermission(String str);
}
接下来,定义一个可以调用接口(interface)方法并存储结果的runnable:
import java.util.concurrent.CountDownLatch;
public class AskUser implements Runnable {
final CountDownLatch userInput = new CountDownLatch(1);
IUpdater updater;
String command;
volatile int result;
@Override
public void run() {
try {
result = updater.askPermission(command);
} finally {
userInput.countDown();
}
}
}
CountDownLatch 使一个线程有机会等待另一个线程(或更准确地说:让可运行对象达到某种状态)。更新后的 Connection
实现展示了这个小技巧:
public class Connection implements Runnable {
IUpdater updater;
Connection(IUpdater u){updater = u;}
@Override
public void run() {
String command = "download_file"; //=getCommand(); from a socket
if(command.equals("download_file")) {
AskUser ask = new AskUser();
ask.command = command;
ask.updater = updater;
SwingUtilities.invokeLater(ask);
try {
ask.userInput.await();
} catch (Exception e) {
// waiting for user input was interrupted
}
System.out.println("Result: " + ask.result);
}
}
}
一般来说,如果您在从 Runnable 获取值时遇到问题,请将 Runnable 设为单独的类,看看是否可以解决问题。您可以使用一些技巧来创建快捷方式(因此您不必为 Runnable 创建单独的类),但这需要特定的知识并且更难以维护。
我经常使用 CountDownLatch
技巧来使不同的 Runnable 同步或了解彼此的状态。给定正确的变量名称,发生的事情应该很明显。
关于java swing线程回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29310955/