Java Swing. Here is such a program, the essence of which is this: there is a window with a button, behind which several enemies are “hidden” (press - kill), as soon as we kill everyone - display the number (zero) in the console. In order not to withdraw the number of enemies ahead of time - we launch in different streams and wait until the first one is completed (shots).

The stream continues to work while there are enemies, the while loop is registered for this, but bad luck - information about the remaining enemies is displayed only if System.out.println () is placed inside the loop, otherwise the stream does not end and zero is not output (be at least a void in the cycle, though a variable that increases with each step). What is the matter? I would not want to litter the console and generally carry out unnecessary operations.

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

    1 answer 1

    Strange enough logic and it would be better to implement it somehow easier. But in your case the problem is? that the variable changes in one thread, but is checked in another and that the second value takes the current value, you must use the keyword volatile , i.e. something like:

     public static volatile int enemy=3; 
    • Thanks, got it. ... is easier to implement, for example, by calling a new class (if the enemy == 0), but in the full program I will need to call this class twice in turn, save and compare the number of "shots" for the first time, and the second, and create a field for this, which is responsible for the number of the person walking (sticking conditions so that nothing has come before). I thought - not a good idea. - user193688
    • @user193688 It is possible when reducing the enemy, you need to triggered a certain event, to which various other handlers are subscribed. Look at the observer pattern - ru.wikipedia.org/wiki/… - Vartlok