Поток с циклом завершается только если внутри него выводится в консоль какая-то информация

478
28 ноября 2016, 18:41

Java Swing. Вот такая вот программка, суть которой такова: есть окно с кнопкой, за которой "прячется" несколько врагов (нажимаем - убиваем), как только убьем всех - выводим кол-во (нолик) в консоль. Чтобы не вывести кол-во врагов раньше времени - запускаем в разных потоках и ждем, пока завершится первый (выстрелы).

Поток продолжает работу, пока есть враги, именно для этого прописан цикл while, но вот незадача -- информация о оставшихся врагах отображается только если внутрь цикла поместить System.out.println(), в противном случае поток не завершается и ноль так и не выводится (будь в цикле хоть пустота, хоть увеличивающаяся с каждым шагом переменная). В чем же дело? Не захотелось бы захламлять консоль и вообще проводить лишние операции.

import java.awt.event.*;
import javax.swing.*;
class MyFrame extends JFrame implements Runnable {
    public static int enemy=3;
    public MyFrame() {
        // TODO Auto-generated constructor stub
        setSize(500, 500);
        JButton jbtn = new JButton(String.valueOf(enemy));
        jbtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                enemy--;
                jbtn.setText(String.valueOf(enemy));
            }
        });
        add(jbtn);
        setVisible(true);
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(enemy>0) 
            System.out.println();   //без этого вывода поток не завершается
                                        //или мы просто не видим информацию?
    }
}
public class Main {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                Thread t1 = new Thread(new MyFrame());
                t1.start();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        try {
                            t1.join();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        System.out.println(MyFrame.enemy);
                    }
                }).start();
            }
        });
    }
}
Answer 1

Достаточно странная логика и лучше бы её реализовать как-то проще. Но в вашем случае проблема в том? что переменная изменяется в одно потоке, а проверяется в другом и чтобы во втором бралось актуальное значение надо использовать ключевое слово volatile, т.е. что-то типа:

public static volatile int enemy=3;
READ ALSO
Как создать динамическую таблицу?

Как создать динамическую таблицу?

Идея такая: пользователь создает на странице запрос типа:

723
Нужен словарик для парса

Нужен словарик для парса

Есть готовая программа для обучения английского языкаНо ей нужны сами слова и не мало

480
get JSON with twitch API in java [требует правки]

get JSON with twitch API in java [требует правки]

guys, i have the next problem: I want to get an information about stream using twitch API in javaI have a client ID and syntax of needed cURL request, but i don't now how to combine all these elements and to get a json object with the information about the stream

482
Ввод пароля PasswordField

Ввод пароля PasswordField

Доброго времени сутокПодскажите пожалуйста как можно сделать для passwordfield, чтобы при нажатии на кнопку входа выскакивало сообщение "Не введен...

477