java swing线程回调

标签 java multithreading swing

我正在尝试使用 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/

相关文章:

java - 为什么我的 JFrame 不响应鼠标和窗口更改?

java - 无法将两个项目绘制到 Jframe

java - JNI for java 在 ubuntu 中使用 eclipse

java - 如何在类路径中为 ant 脚本添加一个文件夹?

java - Akka:Java 中的 Flow 相当于什么

java - Java中的线程与C++中的线程有什么不同?

iphone - 核心文本: counting pages in background thread

java - 循环重绘组件

c# - C#中的线程中止

java - 父 JPanel - 如何监听子 JPanel 组件生成的事件?