Why doesn't the program end?

I am new to using the Timer class, so I am trying to experiment with it before including it in my project. I wonder why this program does not end when the count reaches 5. The program continues to work, although the condition for the while loop is not satisfied.

package Timer; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.Timer; public class demo { private static int count; public static void main(String[] args) { ActionListener executeThis = new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub System.out.println("Hello"); count++; } }; Timer timer = new Timer(500, executeThis); timer.setInitialDelay(1000); timer.start(); while(count < 5){ } } } 
+5
source share
5 answers

You must add:

 timer.stop(); 

To stop timer scheduling.

Another problem is the use of a non-atomic variable in a multi-threaded environment. Instead, you can use AtomicInteger.

You can do this inside the actionPerformed method if count == 5.

+2
source

to stop the timer

 import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.concurrent.atomic.AtomicInteger; public class Test1 { private static AtomicInteger count = new AtomicInteger(0); public static void main(String[] args) { ActionListener executeThis = new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub System.out.println("Hello"); count.getAndIncrement(); } }; Timer timer = new Timer(500, executeThis); timer.setInitialDelay(1000); timer.start(); while(count.get() < 5){ } timer.stop(); } } 

but I think this will be the right way to do it

 import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.concurrent.atomic.AtomicInteger; /** * User: Romeo Sheshi * Date: 21/03/16 * Time: 12:12 */ public class Test { private static AtomicInteger count = new AtomicInteger(0); private static Timer timer; public static void main(String[] args) { ActionListener executeThis = new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub System.out.println("Hello"); if( count.incrementAndGet()==5){ stopTimer(); } } }; timer = new Timer(500, executeThis); timer.setInitialDelay(1000); startTimer(); while ( count.get()<5){} } public static void startTimer(){ timer.start(); } public static void stopTimer(){ timer.stop(); } } 
+2
source

There are two problems:

  • The timer continues to work if not stopped.
  • The static variable count is not synchronized between threads.

Check out this explanation from Gray about synchronization between threads: Static variables and multithreading in java. It explains that each thread has its own copy of the static variable. To avoid this, declare a volatile variable.

For simple testing like this example, you will need a volatile variable. For critical situations, when you need real-time synchronization between threads, use AtomicInteger.

 private static volatile int count; 

Be sure to stop the timer using the timer.stop () function. Incorrectly adding Thread.sleep to the loop, this protects the CPU resources and allows thread synchronization for non-volatile variables.

 while (count < 5) { Thread.sleep(10); } timer.stop(); 

You can find out more about the difference between a variable and AtomicInteger here: What is the difference between atomic / mutable / synchronized?

+2
source

This is Romeo Sheshi's supporting answer

This code has been tested:

  • Windows Java 1.7.0_75 using Netbeans 8 & command line
  • MacOS 10.11.3; Java 1.8.0_20 using Netbeans 8 and terminal

In both cases, the program ends after the counter reaches 5

 import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.concurrent.atomic.AtomicInteger; import javax.swing.Timer; public class Test { private static AtomicInteger count = new AtomicInteger(0); public static void main(String[] args) { ActionListener executeThis = new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub System.out.println("Hello"); count.getAndIncrement(); System.out.println(count); } }; Timer timer = new Timer(500, executeThis); timer.setInitialDelay(1000); timer.start(); while (count.get() < 5) { } System.out.println("On the outside..."); timer.stop(); } } 
+1
source

The best and easiest way to do this is

 import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.Timer; public class demo { private static int count; public static void main(String[] args) { ActionListener executeThis = new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub System.out.println("Hello"); count++; if(count==5){ System.exit(0); } } }; Timer timer = new Timer(500, executeThis); timer.setInitialDelay(1000); timer.start(); while(count < 5){ } } } 
-1
source

Source: https://habr.com/ru/post/1245536/


All Articles