• Java并发基础02. 传统线程技术中的定时器技术


    传统线程技术中有个定时器,定时器的类是Timer,我们使用定时器的目的就是给它安排任务,让它在指定的时间完成任务。所以先来看一下Timer类中的方法(主要看常用的TimerTask()方法):

    前面两个是在指定延迟后执行或者重复执行,后面两个是在指定时间执行或者重复执行。我们以前两个为例来研究一下定时器的使用。
    先写一个简单的使用定时器的demo,然后慢慢引申。

    public class TraditionalTimer {
    
    	public static void main(String[] args) {
    		//简单定时器的demo
    		new Timer().schedule(new TimerTask() {			
    			@Override
    			public void run() {
    				//实际中会扔一个对象进来,我们就可以在这里操作这个对象的所有方法了
    				System.out.println("--boom--");//爆炸
    			}
    		}, 2000,3000); 
    
    		//打印秒钟,一秒输出一次,用来方便观察的
    		while(true) {
    			System.out.println(new Date().getSeconds());
    			try {
    				Thread.sleep(1000);
    			} catch(Exception e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    

    我们用匿名内部类来定义了一个TimerTask对象,需要重写run()方法,然后运行这个程序,可以看出来第一次2秒钟后打印“--boom--,后面每隔3秒打印一次。
    我们也可以自己来实现上面这个重复执行,我们用定时器的“连环套”!也就是定时器中再套定时器,一个定时器任务执行完了,在任务的最后再装一个定时器。那么我们需要先定义一个自己的定时器任务,在自己的定时器任务中再装一个定时器,把自定义的定时器任务扔进去。然后我们开启定时器的时候把自己定义的定时器任务扔进去即可。如下:

    public class TraditionalTimer {
    
    	public static void main(String[] args) {
    		
    		//自定义一个定时器任务
    		class MyTimerTask extends TimerTask {			
    			@Override
    			public void run() {
    				System.out.println("--boom--");
    				//任务执行完再装一个定时器,扔进自定义的定时器任务
    				new Timer().schedule(new MyTimerTask(), 3000);
    			}
    		}
    		new Timer().schedule(new MyTimerTask(), 2000);//外面开启定时器
    		
    		while(true) {//打印秒钟,一秒输出一次
    			System.out.println(new Date().getSeconds());
    			try {
    				Thread.sleep(1000);
    			} catch(Exception e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    

    这样的话,我们通过定时器的“连环套”很轻松的实现了连环爆炸。但是现在问题来了,上面提供的方法中重复执行都是每隔固定的时间,如果我想要隔2秒执行一次,再隔4秒执行一次,再隔2秒执行一次,再隔4秒执行一次……这该如何实现呢?
    可以这样,我们定义一个全局的私有成员变量来记录爆炸次数,奇数的时候隔2秒炸,偶数的次数的话隔4秒炸,或者反过来也行,修改如下:

    public class TraditionalTimer {
    
    	private static int count = 0; //记录爆炸的次数
    	public static void main(String[] args) {	
    
    		class MyTimerTask extends TimerTask {			
    			@Override
    			public void run() {
    				count = (count + 1) % 2; //结果只有0和1
    				System.out.println("--boom--");
    				new Timer().schedule(new MyTimerTask(), 2000+2000*count);//根据count结果设定新的定时时间
    			}
    		}
    		new Timer().schedule(new MyTimerTask(), 2000);
    		
    		while(true) {//打印秒钟,一秒输出一次
    			System.out.println(new Date().getSeconds());
    			try {
    				Thread.sleep(1000);
    			} catch(Exception e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    

    这样的话,我们就实现了自定义爆炸间隔了。上面这个是通过定义一个全局私有变量来实现,其实我们也可以这么干:不是要实现两个不同时间间隔的连环炸么?我可以定义两个定时器任务A和B,在A执行完开启定时器,把B任务装进去,B执行完开启定时器把A装进去,这样也可以。如下:

    public class TraditionalTimer {
    
    	public static void main(String[] args) {
    		
    		new Timer().schedule(new MyTimerTaskA(), 2000);//A和B随便开一个
    		
    		while(true) {//打印秒钟,一秒输出一次
    			System.out.println(new Date().getSeconds());
    			try {
    				Thread.sleep(1000);
    			} catch(Exception e) {
    				e.printStackTrace();
    			}
    		}
    	}
    
    }
    //自定义两个定时器任务类,继承TimerTask即可
    class MyTimerTaskA extends TimerTask {
    
    	@Override
    	public void run() {
    		System.out.println("--boomA--");
    		new Timer().schedule(new MyTimerTaskB(), 4000);
    	}			
    }
    class MyTimerTaskB extends TimerTask {
    
    	@Override
    	public void run() {
    		System.out.println("--boomB--");
    		new Timer().schedule(new MyTimerTaskA(), 2000);
    	}	
    }
    

    这样就可以实现自定义时间间隔的连环炸了。传统的定时器技术就总结这么多吧~
    更多优质文章和资源,请关注公众号:【程序员私房菜】。

  • 相关阅读:
    《运营笔记》:主要是猫扑论坛运营经验。3星。
    《澄明之境》:二十年期货交易员的经验:投资没有圣杯,控制风险,在市场阶梯式上升过程中赚钱。3星
    《好好说话》:常见沟通场景的应对误区与应答思路、应答句式。4星。
    《尖叫感》:是近20-30年来尤其是近3-5年来的优秀广告文案的整理汇编。3星
    《石油,用得完吗》:石油会比较缓慢地被替代。3星
    Discuz常见大问题-如何自定义单个页面
    Discuz常见大问题-如何DIY一个独立页面
    Discuz常见大问题-如何使用云采集插件
    Discuz常见大问题-如何使用图片轮播器
    Discuz常见大问题-如何在自定义页面使用首页四格
  • 原文地址:https://www.cnblogs.com/eson15/p/9824647.html
Copyright © 2020-2023  润新知