【问题标题】:Java, strange bugs. Android & Swing [duplicate]Java,奇怪的错误。 Android 和 Swing [重复]
【发布时间】:2020-08-04 08:19:04
【问题描述】:

我已经更新了这个问题,我创建了一个有以下问题的简单程序。

这是有效的版本代码:

    package com.company;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Main {
    static boolean readytoconnect = false;

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setSize(500, 500);
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        frame.setVisible(true);

        JPanel panel = new JPanel();
        frame.add(panel);
        panel.setBounds(0, 0, frame.getWidth(), frame.getHeight());
        panel.setBackground(Color.lightGray);
        panel.setLayout(null);

        JButton connect = new JButton("Connect");
        panel.add(connect);
        connect.setBounds(200, 200, 80, 40);
        connect.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                readytoconnect = true;
            }
        });

        Thread threadtoconnect = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("WAITING TO CONNECT");
                    if (readytoconnect) {
                        System.out.println("CONNECTED");
                    }
                }
            }
        });
        threadtoconnect.start();
    }
}

这是不起作用的版本代码:

package com.company;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Main {
    static boolean readytoconnect = false;

public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setSize(500, 500);
    frame.setLocationRelativeTo(null);
    frame.setResizable(false);
    frame.setVisible(true);

    JPanel panel = new JPanel();
    frame.add(panel);
    panel.setBounds(0, 0, frame.getWidth(), frame.getHeight());
    panel.setBackground(Color.lightGray);
    panel.setLayout(null);

    JButton connect = new JButton("Connect");
    panel.add(connect);
    connect.setBounds(200, 200, 80, 40);
    connect.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            readytoconnect = true;
        }
    });

    Thread threadtoconnect = new Thread(new Runnable() {
        @Override
        public void run() {
            while (true) {
                //System.out.println("WAITING TO CONNECT");
                if (readytoconnect) {
                    System.out.println("CONNECTED");
                }
            }
        }
    });
    threadtoconnect.start();
}

}

它们之间的区别在于,第一个有效,在 'IF' 之前有输出,而第二个无效,没有输出。

【问题讨论】:

  • 我猜你的线程崩溃了。检查您的 stderr 输出是否有异常。
  • 你有一个非常短的循环,并且不能保证 threadtoconnect 会看到 readytoconnect 的更新值。您可以使readytoconnect 变得易变,但实际上您应该放弃执行等待循环的想法。你想做什么?
  • 在这种情况下,我在 Java 中使用 Swing 库,但我需要适用于 Android 的算法,因为无法在单击按钮事件中启动线程,我必须始终保持线程处于活动状态并准备执行在按钮侦听器中运行的代码
  • 如果我在 volatile 工作中声明 readytoconnect 变量!!!我从来不知道volatile类型的存在,我想知道更多。
  • 那么也许你应该提出一个关于保持“线程处于活动状态并准备好执行代码”的 android 问题。 Java 提供了多种等待条件的技术。在您的示例中,您正在创建一个新线程,因此它已经不符合您的条件。

标签: java multithreading swing serversocket


【解决方案1】:

Android 不支持 Swing 库,您必须使用 Android SDK 中的函数来获取输入等。

我建议在 Android Docs 中查找“OnClickListener”等

【讨论】:

  • 是的,我知道Android不支持Swing库,其实这里我使用的是Android库。我命名 Swing 是因为我列出的问题之一(即输出中的问题)存在于我使用 Swing 库开发的程序中。
  • 这没有回答所提出的问题。
  • @RyanM 嗯?他们无法让 Swing/AWT 在 Android 上运行,我认为这是因为 Swing 不能在 Android 上运行
  • 这个问题已经被编辑过了,但是当我写这个时,there was no Swing code in the question,它已经使用了AndroidOnClickListener。该问题还询问了尝试在 Android 上使用 Swing 不会导致的问题(这将导致项目无法编译,或者如果您以某种方式编译它,则会立即崩溃)。
【解决方案2】:

首先,我将指出两个版本的代码存在的几个问题:

  1. 您似乎有两个线程读取和更新共享的readytoscan 字段而没有任何明显的同步。除非该字段声明为volatile,否则容易导致内存异常。

  2. 分配给readytoscanrun() 方法中的代码应该是分配false 给它...而不是true

  3. 代码会泄漏打开的套接字!

  4. 您正在创建Thread 的匿名子类,它会覆盖run() 方法。更传统的做法是创建Thread 的实例并将Runnable ... 或lambda 传递给它。


我认为以上任何内容都不能解释您报告的奇怪行为。内部循环只能运行一次的唯一原因(我可以看到)是run() 方法是否崩溃。具体来说,内部循环中的某些东西必须抛出未经检查的异常。

要跟踪此问题,您可以向try 添加额外的catch (Throwable ...) 并记录它捕获的异常。如果这不能解释该行为,请尝试创建minimal reproducible example。例如,您可以简化纯 Java 版本,使其不使用 Swing ...我认为这与问题无关。

我的猜测是问题来自new Socket(...) 电话。例如,它可能是SecurityException


我上面描述的问题适用于 Android 和 Java 使用 Swing 库,所以假设 Java 是一般问题。

假设错误出在 Java、Android 或 Swing 中是一个糟糕的策略……只是因为您无法在代码中找到原因。可以这样想:Java / Android 平台为数百万其他开发人员工作,并在数十亿台设备上运行(我猜这些数字)。他们已经(在 Java 案例中)工作了 20 多年。其他人已经发现、报告和修复的 Java 和 Android 平台存在根本性错误的可能性微乎其微。

【讨论】:

  • 感谢您的回答,我会尽力按照您说的去做。 (我曾尝试将 Runnable 与 Thread 一起使用,但我遇到了同样的问题)我同意你的观点,我不必假设该错误在 java / android 中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-12
相关资源
最近更新 更多