-2

I have updated this ask, i created a simple program with the following problem.

This is the version code that work:

    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();
    }
}

This is the version code that don't work:

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();
}

}

the difference between these is that in the first, which works, there is the output before the 'IF' and in the second, which does not work, there is no output.

Davide
  • 1
  • 3
  • I'm guessing your thread is crashing. Check your stderr output for exceptionss. – Ryan M Aug 05 '20 at 01:11
  • You have an insanely short loop, and there is not guarantee that the threadtoconnect will see the updated value of `readytoconnect`. You could make `readytoconnect` volatile, but you should actually ditch this idea of performing a wait loop. What do you want to do? – matt Aug 05 '20 at 06:44
  • In this case I am in Java with the use of the Swing library, but I need the algorithm for Android because, being unable to start a thread inside the click of a button event, I must always keep the thread active and ready to execute the code that was to run inside the button listener – Davide Aug 05 '20 at 06:59
  • If i declare the readytoconnect variable in volatile work!!!! I have never known of the existence of the volatile type, I would like to know more. – Davide Aug 05 '20 at 07:05
  • Then maybe you should make an android question about keeping a "thread active and ready to execute code." Java offers numerous techniques for waiting on a condition. In your example you are creating a new thread so it already doesn't meet your criteria. – matt Aug 05 '20 at 07:07

2 Answers2

0

Android does not support the Swing library, you must use functions from the Android SDK to get input etc.

I would advise looking up "OnClickListener" or the like in the Android Docs

Emily-TTG
  • 531
  • 3
  • 18
  • Yes, I know that Android does not support the Swing library, in fact here I use the Android libraries. I named Swing because one of the problems I listed (i.e. the one on the output) is present in a program of mine developed with the Swing library. – Davide Aug 04 '20 at 11:00
  • 1
    This does not answer the question that was asked. – Ryan M Aug 05 '20 at 01:10
  • @RyanM Hm? They are having trouble getting Swing/AWT to function on Android, I presume the this is because Swing does not work on Android – Emily-TTG Aug 05 '20 at 10:27
  • The question has since been edited, but when I wrote this, [there was no Swing code in the question](https://stackoverflow.com/revisions/63242798/3), and it already used the Android `OnClickListener`. The question also asked about an issue that would not have been caused by trying to use Swing on Android (which would result in either the project failing to compile, or if you somehow got it to compile, immediately crashing). – Ryan M Aug 05 '20 at 20:23
0

First, I will point out a couple of problems with both versions of the code:

  1. You appear to have two threads reading and updating a shared readytoscan field without any obvious synchronization. Unless that field is declared as volatile, that is liable to lead to memory anomalies.

  2. The code in the run() method that assigns to readytoscan should probably be assigning false to it ... not true.

  3. The code will leak open sockets!

  4. You are creating an anonymous subclass of Thread which overrides the run() method. It is more conventional to create an instance of Thread and pass it a Runnable ... or a lambda.


I don't think that any of the above explain the strange behavior that you reported though. The only cause (that I can see) for the inner loop can run just once is if the run() method is crashing. Specifically, something in the inner loop must be throwing an unchecked exception.

To track this down, you could add an extra catch (Throwable ...) to the try and log the exception that it catches. If that doesn't yield an explanation for the behavior, try creating a minimal reproducible example. For example, you could simplify the plain Java version so that it didn't use Swing ... which I don't think is implicated in the problem.

My guess is that the problem is coming from the new Socket(...) call. For example, it could be a SecurityException.


The problems I described above are for both Android and Java with the use of the Swing library, so let's say Java is the problem in general.

It is a bad strategy to assume that the bug is in Java or Android or Swing ... just because you can't find a cause in your code. Think of it this way: the Java / Android platforms work for millions of other developers and run on billions of devices (I am guessing these numbers). They have worked for (in the Java case) 20+ years. The chances that there is something fundamentally wrong with the Java AND Android platforms that other people haven't already found, reported and fixed is vanishingly small.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Thanks for answer, I will try to do what you told me. (I have tried to use Runnable with Thread but i got the same problem) I agree with you that I didn't have to assume that the bug was in java / android. – Davide Aug 05 '20 at 06:08