Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么在Java中打印所有正在运行的线程会解除应用程序的阻塞?_Java_Multithreading_Javafx - Fatal编程技术网

为什么在Java中打印所有正在运行的线程会解除应用程序的阻塞?

为什么在Java中打印所有正在运行的线程会解除应用程序的阻塞?,java,multithreading,javafx,Java,Multithreading,Javafx,我在JavaFX中创建了一个GUI应用程序,该应用程序与串行设备通信(我使用一个。当我想要获取数据时,我发送一个通信,然后等待1s,直到等待函数终止。当我单击其中一个按钮(用于启动设备、用于识别等)时,也会发送通信。在开发过程中,我注意到一个错误——当我点击太多按钮或点击发送多个通信的按钮时,通信挂起(但只有在收到消息时,我仍然可以发送单向通信,例如启动设备) 通信主要由我自己的类SerialPortDevice处理。我创建一个类类型的对象,然后调用特定的方法。下面是等待消息的方法: priva

我在JavaFX中创建了一个GUI应用程序,该应用程序与串行设备通信(我使用一个。当我想要获取数据时,我发送一个通信,然后等待1s,直到等待函数终止。当我单击其中一个按钮(用于启动设备、用于识别等)时,也会发送通信。在开发过程中,我注意到一个错误——当我点击太多按钮或点击发送多个通信的按钮时,通信挂起(但只有在收到消息时,我仍然可以发送单向通信,例如启动设备)

通信主要由我自己的类SerialPortDevice处理。我创建一个类类型的对象,然后调用特定的方法。下面是等待消息的方法:

private String waitForMessage() throws SerialPortException {
    long operationStartTime = System.currentTimeMillis();
    long connectionTimeout = SerialPortCommunicationParameters.CONNECTION_TIMEOUT_IN_MILLIS;
    String resultMessage = "";
    do {
        if (readEventOccurred) {
            System.out.println();
            resultMessage = receiveMessage();
            System.out.println("After receiving a message");
            messageReceived = true;
        }
    } while (((System.currentTimeMillis() - operationStartTime) < connectionTimeout) && (!messageReceived));
    if (!readEventOccurred) {
        resultMessage = NO_RESPONSE;
    }
    System.out.println("Time elapsed: " + (System.currentTimeMillis() - operationStartTime + "ms"));
    return resultMessage;
}
ReadEventOccursedSerialPortDevice类中的一个布尔字段,其中包含WaitFormMessage函数。另外,WaitFormMessage由另一个函数调用,singleConversation

String singleConversation(String testMessage) {
    String resultMessage = NO_RESPONSE;
    try {
        openConnection();
        sendMessage(testMessage);
        resultMessage = waitForMessage();
        closeConnection();
    } catch (SerialPortException e) {
        e.printStackTrace();
        return resultMessage;
    }
    System.out.println();
    readEventOccurred = false;
    messageReceived = false;

    return resultMessage;
}
。。。这是将ReadEventOccursed设置为false的唯一函数。它是串行端口设备类中的一个“顶级”函数,处理发送和接收与设备的通信。
因此,通信是这样的:
按钮单击->按钮处理程序调用->设备。singleCommunication(特定于按钮的\u Communication)->一些方法运行,然后到达WaitFormMessage->方法等待事件发生1s->事件发生(每次-我得到“串行事件发生”通信)->ReadEventOccursed设置为true->如果还有时间的话(总有一些时间剩余,一切都会持续一毫秒),消息是通过WaitFormMessage方法接收的

如果我单击延迟较短的按钮(比如2-3秒),或者我没有单击这些按钮,那么就没有问题了。在不同的情况下,会发生奇怪的事情。我仍然会收到消息“Serial Event Occursed”(因此我认为ReadEventOccursed也被设置为true)但WaitFormMessage函数不执行

if(readEventOccured)
语句的代码。此外,我必须再次运行应用程序才能与设备通信(我的意思是接收数据,发送工作正常)

解决我问题的方法是在ReadEventOccursed标志中添加“volatile”修饰符(顺便说一句,事情有时进展得很快)。但我并不满意。我想让代码在没有“volatile”的情况下正确运行.我的同事想出了一个主意,当我点击按钮并调用通信时,正在创建的线程出现了问题-可能有什么东西在某处阻止了其他事情?我做的第一件事是打印所有当前运行的线程,然后…伙计,它解决了一个问题。应用程序不再挂起。真的,我执行了“挂起”场景10-20次,带和不带

      Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
      System.out.println(threadSet);
Set threadSet=Thread.getAllStackTraces().keySet();
系统输出打印LN(螺纹组);
在WaitFormMessage方法的开始,结果是明确的——它以某种方式解决了我的问题。
我几乎可以肯定的是,获取和打印线程本身并不是一个解决方案。这是一个正在进行的过程,但我不知道这是什么。有什么有用的信息吗?也许更好地理解Java中的线程会对我有所帮助?或者是其他什么

干杯

解决我问题的方法是在ReadEventOccursed标志中添加“volatile”修饰符(顺便说一句,事情有时进展得很快)。但我并不满意。我想让代码在没有“volatile”的情况下正确运行

添加volatile修复了这个问题,这表明当涉及多个线程时,Java内存模型缺乏保证。简单地说,除了特定情况外,无法保证一个线程上的更改在其他线程上是可见的

打印“修复”问题的原因可能是:

  • 更改程序的时间,可能意味着它失败的情况不再存在
  • 暂时挂起线程以读取其当前状态,可能JVM也会将此作为同步内存的机会
  • 多线程通信很困难,因此我建议您查看中可用的类,这些类保证您可以使用它们更优雅地解决问题

    解决我问题的方法是在ReadEventOccursed标志中添加“volatile”修饰符(顺便说一句,事情有时进展得很快)。但我并不满意。我想让代码在没有“volatile”的情况下正确运行

    添加volatile修复了这个问题,这表明当涉及多个线程时,Java内存模型缺乏保证。简单地说,除了特定情况外,无法保证一个线程上的更改在其他线程上是可见的

    打印“修复”问题的原因可能是:

  • 更改程序的时间,可能意味着它失败的情况不再存在
  • 暂时挂起线程以读取其当前状态,可能JVM也会将此作为同步内存的机会
  • 多线程通信很难实现,因此我建议您查看中的可用类,这些类可以保证您能够更优雅地解决问题。

    您所做的是。如果我们将代码提炼为其基本位,我们会得到如下结果:

    boolean flag = false;
    
    void consume() {
        while (true) {
           if (flag) {
              //we received flag, hooray
           }
        }
    }
    
    void produce() {
        flag = true;
    }
    
    现在,如果
    product()
    consume()
    在不同的线程中运行,则绝对不能保证
    consume()
    将看到
    标志设置为true。
    volatile
    创建内存b
    boolean flag = false;
    
    void consume() {
        while (true) {
           if (flag) {
              //we received flag, hooray
           }
        }
    }
    
    void produce() {
        flag = true;
    }