Java timer使用问题——如何结束定时器

RunningCamel 2016-05-20 10:57:26
一个简单的定时器程序:我想要的功能是每秒钟i值递增一次,然后打印出来,然后为10时停止。但是现在是一直增加,计数器停不下来。我是新手,帮忙看看时什么原因啊!


import java.util.Timer;
import java.util.TimerTask;

class MyTask extends TimerTask{
private int i = 0;
private boolean flag = false;

public void run(){
i++;
if(i > 10){//当i增加到10时,将flag=true
flag = true;
}
System.out.print(i + " ");
}

public boolean getFlag(){
return this.flag;
}

// public int getValue(){
// return this.i;
// }
}

public class MatchDemo{
public static void main(String args[]){
Timer t = new Timer();
MyTask mytask = new MyTask();
t.schedule(mytask,1000,1000);
while(true){
if(mytask.getFlag()){//flag为true时
t.cancel();//停止计时器任务
break;
}
}
}
}


结果:(一直打印,根本停不下来)
...全文
744 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
小灰狼 2016-05-21
  • 打赏
  • 举报
回复
引用 7 楼 XZ_ZC 的回复:
大概有些明白了:就是说,我主线程里只是开启了定时器任务,而什么时候这个定时器结束,是有任务来决定的。主线程开启任务后就执行完了。当我在任务中设定好的(或者像你说的AWT/Swing中的控件事件,这只不过是外部条件)条件条件满足时,就会去调用监视器已经设定好的程序来进行处理。这一过程也是在任务的一部分了。不知道我理解得对不对
单独就你的这个问题来说,可以这么理解 利用模式后更重要的效果是实现逻辑的分离。要达到你的目标,使用1楼的方案是最简单的,但是缺点也很明显,你必须在你的 task 中处理你的业务逻辑。而使用模式之后,变成了一种通知机制,某个事件发生(你的变量大于10了)时,触发事件,通过监听器接口通知注册了监听的程序,至于是不是有人注册了监听器(通过 listener == null)判断,监听器作什么业务处理,那是另外一个模式要做的事,你的 task 里只管触发事件,并把足够的信息通过参数传给监控程序;而将来如果处理这些事件的逻辑发生变化,也和你的 task 无关。从而达到低的耦合。
RunningCamel 2016-05-20
  • 打赏
  • 举报
回复
嗯 这样可以,谢谢!!!我当时想尝试在类中来取消,但是不知道对象字母进来。这样就是直接调用本类对象就可以了
小灰狼 2016-05-20
  • 打赏
  • 举报
回复
主线程跑得太快了,只要在主线程的 while(true) 里随便休眠一下就解决了,至于为什么会导致这个结果我也奇怪 并且主线程这么个死循环,会占很大的CPU资源,一般不会这么做 另外,你应该使用一些如观察者模式之类的方式,当条件满足时通过回调的方式主动通知主线程cancel timer,而不是在主线程里一直监视状态
skgary 2016-05-20
  • 打赏
  • 举报
回复
因为你cancel的是timer ,而不是task . 直接在11行调this.cancel()即可。
RunningCamel 2016-05-20
  • 打赏
  • 举报
回复
引用 6 楼 hemowolf 的回复:
[quote=引用 5 楼 hemowolf 的回复:] [quote=引用 4 楼 XZ_ZC 的回复:] [quote=引用 2 楼 hemowolf 的回复:] 主线程跑得太快了,只要在主线程的 while(true) 里随便休眠一下就解决了,至于为什么会导致这个结果我也奇怪 并且主线程这么个死循环,会占很大的CPU资源,一般不会这么做 另外,你应该使用一些如观察者模式之类的方式,当条件满足时通过回调的方式主动通知主线程cancel timer,而不是在主线程里一直监视状态
我当时只是想实现这个功能,不知道还有这么多问题。我再看看观察者模式,看能不能用得上。 主线程跑得太快不是更容易检测flag值吗?如果休眠一下的话,会不会出现比如i值现在是10了,但是应为主线程还在休眠,没有让定时器停下来,导致最后i值可能出现大于10的情况呢?乱想了一下,,,不过确实可以解决问题,[/quote] 主线程跑得太快,会占用大量的CPU资源,导致系统性能严重下降,这是最根本的 你第二点担心的是有道理的。所以我说你的主线程是用轮询的方式检查信号量状态变化,这种方式很被动;而如果用一种观察者模式(可能叫这个模式吧,名字我真不想纠结)的方式,使你的主线程处于等待状态,一旦条件满足时,由被观察的对象主动通知你。 其实这种模式和AWT/Swing中的控件事件很相似。比如一个按钮被用户点击时,一个函数就被调用了。但你的程序是不可能时时刻刻地去询问按钮的状态的,而是操作系统检测到控件事件后,主动调用你指定的方法。[/quote] like this:

package test;

import java.util.Timer;
import java.util.TimerTask;

/**
 * 定义监听器
 */
interface FlagStatusListener {
	public void flagValueChanged(boolean newFlagValue);
}

class MyTask extends TimerTask{
	// 监听器对象
	private FlagStatusListener listener;
	
    private int i = 0;
    private boolean flag = false;
     
    public void run(){
        i++;
        if(i > 10){
			boolean oldValue = flag;
			flag = true;
			
			// 发起通知
			if(this.listener != null && oldValue != flag){
				listener.flagValueChanged(flag);
			}
        }
        System.out.print(i + " ");
    }
	
	public MyTask(FlagStatusListener listener){
		this.listener = listener;
	}
}

public class Test {
    public static void main(String args[]){
        final Timer t = new Timer();
        MyTask mytask = new MyTask(
			// 用一个匿名类监听状态变化,等待 timer 主动通知
			new FlagStatusListener (){
			public void flagValueChanged(boolean newFlagValue){
				if(newFlagValue == true)
					t.cancel();
			}
		});
        t.schedule(mytask,1000,1000);
    }
}

[/quote]大概有些明白了:就是说,我主线程里只是开启了定时器任务,而什么时候这个定时器结束,是有任务来决定的。主线程开启任务后就执行完了。当我在任务中设定好的(或者像你说的AWT/Swing中的控件事件,这只不过是外部条件)条件条件满足时,就会去调用监视器已经设定好的程序来进行处理。这一过程也是在任务的一部分了。不知道我理解得对不对
小灰狼 2016-05-20
  • 打赏
  • 举报
回复
引用 5 楼 hemowolf 的回复:
[quote=引用 4 楼 XZ_ZC 的回复:] [quote=引用 2 楼 hemowolf 的回复:] 主线程跑得太快了,只要在主线程的 while(true) 里随便休眠一下就解决了,至于为什么会导致这个结果我也奇怪 并且主线程这么个死循环,会占很大的CPU资源,一般不会这么做 另外,你应该使用一些如观察者模式之类的方式,当条件满足时通过回调的方式主动通知主线程cancel timer,而不是在主线程里一直监视状态
我当时只是想实现这个功能,不知道还有这么多问题。我再看看观察者模式,看能不能用得上。 主线程跑得太快不是更容易检测flag值吗?如果休眠一下的话,会不会出现比如i值现在是10了,但是应为主线程还在休眠,没有让定时器停下来,导致最后i值可能出现大于10的情况呢?乱想了一下,,,不过确实可以解决问题,[/quote] 主线程跑得太快,会占用大量的CPU资源,导致系统性能严重下降,这是最根本的 你第二点担心的是有道理的。所以我说你的主线程是用轮询的方式检查信号量状态变化,这种方式很被动;而如果用一种观察者模式(可能叫这个模式吧,名字我真不想纠结)的方式,使你的主线程处于等待状态,一旦条件满足时,由被观察的对象主动通知你。 其实这种模式和AWT/Swing中的控件事件很相似。比如一个按钮被用户点击时,一个函数就被调用了。但你的程序是不可能时时刻刻地去询问按钮的状态的,而是操作系统检测到控件事件后,主动调用你指定的方法。[/quote] like this:

package test;

import java.util.Timer;
import java.util.TimerTask;

/**
 * 定义监听器
 */
interface FlagStatusListener {
	public void flagValueChanged(boolean newFlagValue);
}

class MyTask extends TimerTask{
	// 监听器对象
	private FlagStatusListener listener;
	
    private int i = 0;
    private boolean flag = false;
     
    public void run(){
        i++;
        if(i > 10){
			boolean oldValue = flag;
			flag = true;
			
			// 发起通知
			if(this.listener != null && oldValue != flag){
				listener.flagValueChanged(flag);
			}
        }
        System.out.print(i + " ");
    }
	
	public MyTask(FlagStatusListener listener){
		this.listener = listener;
	}
}

public class Test {
    public static void main(String args[]){
        final Timer t = new Timer();
        MyTask mytask = new MyTask(
			// 用一个匿名类监听状态变化,等待 timer 主动通知
			new FlagStatusListener (){
			public void flagValueChanged(boolean newFlagValue){
				if(newFlagValue == true)
					t.cancel();
			}
		});
        t.schedule(mytask,1000,1000);
    }
}

小灰狼 2016-05-20
  • 打赏
  • 举报
回复
引用 4 楼 XZ_ZC 的回复:
[quote=引用 2 楼 hemowolf 的回复:] 主线程跑得太快了,只要在主线程的 while(true) 里随便休眠一下就解决了,至于为什么会导致这个结果我也奇怪 并且主线程这么个死循环,会占很大的CPU资源,一般不会这么做 另外,你应该使用一些如观察者模式之类的方式,当条件满足时通过回调的方式主动通知主线程cancel timer,而不是在主线程里一直监视状态
我当时只是想实现这个功能,不知道还有这么多问题。我再看看观察者模式,看能不能用得上。 主线程跑得太快不是更容易检测flag值吗?如果休眠一下的话,会不会出现比如i值现在是10了,但是应为主线程还在休眠,没有让定时器停下来,导致最后i值可能出现大于10的情况呢?乱想了一下,,,不过确实可以解决问题,[/quote] 主线程跑得太快,会占用大量的CPU资源,导致系统性能严重下降,这是最根本的 你第二点担心的是有道理的。所以我说你的主线程是用轮询的方式检查信号量状态变化,这种方式很被动;而如果用一种观察者模式(可能叫这个模式吧,名字我真不想纠结)的方式,使你的主线程处于等待状态,一旦条件满足时,由被观察的对象主动通知你。 其实这种模式和AWT/Swing中的控件事件很相似。比如一个按钮被用户点击时,一个函数就被调用了。但你的程序是不可能时时刻刻地去询问按钮的状态的,而是操作系统检测到控件事件后,主动调用你指定的方法。
RunningCamel 2016-05-20
  • 打赏
  • 举报
回复
引用 2 楼 hemowolf 的回复:
主线程跑得太快了,只要在主线程的 while(true) 里随便休眠一下就解决了,至于为什么会导致这个结果我也奇怪 并且主线程这么个死循环,会占很大的CPU资源,一般不会这么做 另外,你应该使用一些如观察者模式之类的方式,当条件满足时通过回调的方式主动通知主线程cancel timer,而不是在主线程里一直监视状态
我当时只是想实现这个功能,不知道还有这么多问题。我再看看观察者模式,看能不能用得上。 主线程跑得太快不是更容易检测flag值吗?如果休眠一下的话,会不会出现比如i值现在是10了,但是应为主线程还在休眠,没有让定时器停下来,导致最后i值可能出现大于10的情况呢?乱想了一下,,,不过确实可以解决问题,

62,634

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧