【问题标题】:Why is program not terminating?为什么程序没有终止?
【发布时间】:2016-07-09 01:55:47
【问题描述】:

我是使用 Timer 类的新手,因此在将其合并到我的项目之前尝试对其进行试验。我想知道为什么当计数达到 5 时这个程序没有终止。即使 while 循环的条件不满足,程序也会继续运行。

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){

        }
    }

}

【问题讨论】:

  • 为什么要停止?您正在将其作为计时器作业执行。它基本上安排它并在给定的时间间隔后运行它
  • 为什么当我没有while循环时,计时器从不发送actionEvent?如果不需要 while 循环,为什么会发生这种情况?

标签: java swing timer


【解决方案1】:

有两个问题:

  • 计时器在未停止时继续运行。
  • 静态计数变量未在线程之间同步。

查看 Gray 关于线程间同步的解释:Static variables and multithreading in java 他解释说,每个线程都有自己的静态变量副本。为了避免这种情况,请声明变量 volatile。

对于像这个例子这样的简单测试,你只需要一个 volatile 变量。对于需要线程之间实时同步的紧急情况,请使用 AtomicInteger。

private static volatile int count;

确保使用 timer.stop() 停止计时器。在循环中添加一个 Thread.sleep 并没有错,这样可以保护 CPU 资源并允许非易失变量的线程同步。

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

您可以在此处阅读有关 volatile 变量和 AtomicInteger 之间区别的更多信息:What is the difference between atomic / volatile / synchronized?

【讨论】:

  • 你必须深入阅读 Java 中的内存模型和并发性
  • 虽然 volatile 是朝着正确方向迈出的一步,但 AtomicInteger 是一个更好的解决方案(至少从我的经验来看:P)
【解决方案2】:

你应该添加:

timer.stop();

为了停止定时器的调度。

另一个问题是在多线程环境中使用非原子变量。您可以改用 AtomicInteger。

如果 count == 5,您可以在 actionPerformed 方法中执行此操作。

【讨论】:

  • 顺便说一句,这不起作用。该计划仍在继续。
  • 定时器停止,但程序继续更新。还需要一些其他操作。
  • 问题是while-loop 从未看到对count 所做的更改,因为它们位于不同的线程上,这基本上是一个脏读问题
【解决方案3】:

这是对罗密欧佘诗的支持性回答

此代码已经过测试:

  • 窗口;使用 Netbeans 8 和命令行的 Java 1.7.0_75
  • MacOS 10.11.3;使用 Netbeans 8 和终端的 Java 1.8.0_20

在这两种情况下,程序在计数达到 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();
    }

}

【讨论】:

    【解决方案4】:

    用于停止计时器

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

    但我认为这将是正确的方法

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

    【讨论】:

    • 是的,我测试它有效,但我认为这不是使用计时器的正确方法 BobTheBuilder 的 anwser 是正确的方法
    • 我已经复制了你的第一个摘录,并且在我写这篇文章时程序仍在运行。
    • 抱歉,这可能是我的想法停止了我要通过终端进行测试的程序。你的观察可能是正确的
    • 是的,你说得对,第一次提取不起作用问题是计数器没有像 tak3shi 在他的回答中所说的那样递增。我更改了第一个提取物以使其工作
    • @RubioRic 我的代码与第一个示例基本相同,并且在 IDE 和终端中都可以正常工作。您使用的是什么操作系统?
    【解决方案5】:

    最好和最简单的方法是 --

    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){
    
            }
        }
    
    }
    

    【讨论】:

    • 没有必要使用这么生硬的方法,也没有解释为什么while-loop不退出(或者至少在count到达5时不退出,想想我把它发给20)
    • 没有while循环代码无法运行我不知道为什么......如果你有解决方案然后解释一下
    • 我做了,如果你有兴趣看看;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-15
    • 2019-12-21
    • 2020-07-19
    • 1970-01-01
    • 2011-02-28
    • 2022-06-17
    相关资源
    最近更新 更多