线程哈哈

 

       线程的应用在java的学习过程中简直就像开启了一个新纪元,过去的程序都是单线程,即JVM创建主线程顺序执行,直到程序结束,而多线程带来的另一个好消息是我们可以做一些更具有实际应用性的东西出来,比如~秒表

 

                             

   简单说一下线程创建方法,线程有三种常见的创建方法,其中最常见的是第一种

 

  1.      继承Thread 类实现线程
  2.      实现Runnable接口创建线程
  3.      继承TimerTask类实现线程的定时执行
      第一种简单方便,最为常用,第二种先定义一个实现Runnable接口的类,实现它的run()方法,然后将这个类的实例作为Thread的构造方法的参数,创建Thread类的实例,即可作为线程启动,其实Thread本身也是实现了Runnable接口的类,这种方法较第一种的优点就是在类的创建时,该类还可以继承其他类,这是由于java的单继承机制造成的;同时我们当然也可以通过创建内部类方法方便的建立线程,这种方法在编写一些单线程应用时十分方便,在一个方法中就可以启动一个线程,而且这个线程可以直接调用类中的属性和方法,特别注意的是,在方法中启动匿名内部线程时,如果要向这个线程的run方法内传递参数,在创建方法中这个参数必须定义为final类型,对于第三种,有着独特的应用,在定时操作方面(后面在秒表的精度调节部分有代码)。
前面图中是一个界面粗糙的Demo,但对于秒表来说精度是一个很值得注意的问题,因为除了休眠,计时代码的执行也会消耗一部分时间,这会对秒表的精度造成很大的影响,当然这个我们还是可以解决的~
其实只需要将执行代码的时间计算出来,将其包含进休眠的10个毫秒里就可以
	public void run() {

		long lastTime = System.currentTimeMillis();

		while (true) {

			try {
				sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

			// 如果不为空,则添加标签和按钮
			if (!f.getList_lab().isEmpty()) {
				f.add(f.getList_lab().get(f.getList_lab().size() - 1));
				f.add(f.getList_btn().get(f.getList_btn().size() - 1));
				f.validate();
			}

			if (pauseflag) {
				continue;
			}

			long endTime = System.currentTimeMillis();

			if (endTime - lastTime >= 10) {

				lastTime = System.currentTimeMillis();

				count++;
				sec = count / 100;
				ms = count % 100;

				if (sec == 60 && min < 59) {
					count = 0;
					sec = 0;
					min++;
				} else if (sec == 60 && min == 59) {
					hour++;
					min = -1;
					sec = 0;
				}

				String s1 = String.valueOf(hour);
				String s2 = String.valueOf(min);
				String s3 = String.valueOf(sec);
				String s4 = String.valueOf(ms);

				if (hour < 10) {
					s1 = "0" + s1;
				}
				if (min < 10) {
					s2 = "0" + s2;
				}
				if (sec < 10) {
					s3 = "0" + s3;
				}
				if (ms < 10) {
					s4 = "0" + s4;
				}

				lab_time.setText(s1 + ":" + s2 + ":" + s3 + ":" + s4);

			}

		}

	}
       总的来说,,,,,,这种方法不是很专业,因为我们可以方便的使用定时器来完成定时任务,只需要两步就可以完成向这种方法的变化,将原来继承Thread的类改为继承TimerTask(定时任务),在主类创立一个该对象的实例和一个定时器对象的实例,再调用定时器的schedule方法就可以,图片就不展示了,因为和前面的相比完全看不出来效果     ^_^" 尴尬的笑.....
       做秒表神马的都是小case,我们线程更多的应用在游戏方面(目前看来),游戏中画图的部分,比如一个小球。。。。。
       当然,效果还是很值得改进的,我们甚至还可以让图片动起来。。。。
        1. 这是一般添加图片的方法:
// 利用JLabel添加图片
 ImageIcon bg = new ImageIcon("src/yk/time140319/hh.jpg");
 JLabel lab_image = new JLabel();
 lab_image.setIcon(bg);
 this.add(lab_image);
          这种方法会使图片以一个组件的形式表现出来,符合一般组件的规律,比如布局等等。
        2.drawImage显示图片
	// 重绘方法显示静态图片,可重绘
	public void paint(Graphics g) {
		super.paint(g);
		int x = 0;
		int y = 0;
		ImageIcon bg = new ImageIcon("src/yk/time140319/hh.jpg");
		g.drawImage(bg.getImage(), x, y, null);
	}
           这个方法用drawImage函数,但必须要在重绘函数中画出,否则不会显示。
        3.那怎么让图片动起来呢,可以试一下在paint函数加一个while(true)循环,不断改变坐标值,敢试的话,呵呵,对不起,程序已死。。。这时候就该用线程解决了,顺便利用缓冲区画布使图像不再闪动,完美效果一次成型!
// 利用缓冲区加强效果
		BufferedImage bu = new BufferedImage(f.getWidth(), f.getHeight(),
				BufferedImage.TYPE_INT_RGB);
		Graphics gr = bu.getGraphics();
		// 填充缓冲区,不能用draw函数或clear函数
		gr.fillRect(0, 0, f.getWidth(), f.getHeight());
		gr.drawImage(bg.getImage(), x, y, null);
		gr.drawImage(bg.getImage(), x + bg.getIconWidth(), y, null);
		if (x + bg.getIconWidth() < 0) {
			x = 0;
		}
		x--;
		// BufferedImage图像显示的坐标
		g.drawImage(bu, 0, 0, null);
   
             刚刚在调试的时候发现图像移动的速度是与休眠时间有关的。
 
 
 
 
 

 

 

 


 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值