服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

java applet动画设计

  applet是在浏览器中运行的小程序,java也是从applet开始风靡世界的。通过编写这个applet,我们可以学习到如下知识:

  1. applet及japplet中的主要接口

  2. 图像的装载及mediatracker的使用

  3. 线程的使用及多个线程直接的通讯

  4. thread.join()方法的使用

  5. volatile关键字的使用

  首先看看运行效果:点击运行

  动画的主要部分是一个applet,从codebase中读取一组图片文件,然后每隔1秒轮换显示一张。代码如下:

import javax.swing.japplet;
import java.awt.graphics;
import java.awt.image;
import java.awt.mediatracker;
public class animate extends japplet
{
 //图片数量
 private static final int num_of_pic = 4;
 int count;
 image pics[];
 timerthread timer;
 public void init()
 {
  count = 1;
  pics = new image[num_of_pic];
  mediatracker tracker = new mediatracker(this);
  for(int i = 0; i<num_of_pic; i++)
  {
   //将图片按照0,1,...,num_of_pic -1,放置在目录中,格式为.jpg
   pics[i] = getimage(getcodebase(), new integer(i).tostring()+".jpg");
   tracker.addimage(pics[i], 0);
  }
  tracker.checkall(true);
 }
 public void start()
 {
  timer = new timerthread(this, 1000);
  timer.start();
 }
 public void stop()
 {
  timer.shouldrun = false;
  try
  {
   timer.join();
   //等待timer线程退出
  }
  catch (interruptedexception e){};
 }
 public void paint(graphics g)
  {
   g.drawimage(pics[count++], 0, 0, null);
   if(count == num_of_pic) count = 0;
  }
}

  动画的控制由一个专门的线程timerthread进行处理,

import java.awt.component;
public class timerthread extends thread
{
 component comp;
 int timediff;
 // shouldrun声明为volatile
 volatile boolean shouldrun;
 public timerthread(component comp, int timediff)
 {
  super("timerthread(" + timediff + " millseconds");
  this.comp = comp;
  this.timediff = timediff;
  shouldrun = true;
 }
 public void run()
 {
  while(shouldrun)
  {
   try
    {
    comp.repaint();
    sleep(timediff);
    }
   catch (exception e){}
   }
 }
}

  mediatracker的使用

  在applet中获取一个图像文件,可以调用applet的getimage()方法。但是getimage方法会在调用后马上返回,如果此时马上使用getimage获取的image对象,而这时image对象并没有真正装载或者装载完成。所以,我们在使用图像文件时,使用java.awt包中的mediatracker跟踪一个image对象的装载,可以保证所有图片都加载完毕。使用mediatracker需要如下三个步骤:

  1、实例化一个mediatracker,注意要将显示图片的component对象作为参数传入。

mediatracker tracker = new mediatracker(this);

  2、将要装载的image对象加入mediatracker

pics[i] = getimage(getcodebase(),
new integer(i).tostring()+".jpg");
tracker.addimage(pics[i], 0);

  3、调用mediatracker的checkall()方法,等待装载过程的结束。

tracker.checkall(true);

  thread.join()的使用

  我们在animate的stop方法中调用timer的join()方法,将timer线程连接(join)到当前线程,当前线程会一致会等待timer线程运行结束后,timer.join()方法才会返回。如果当前线程在等待timer返回的过程中,被其它线程中断了,那么当前线程会抛出interruptedexception。如果不使用thread的join方法,那么只能通过轮询timer线程的状态进行判断了:

while (timer.isalive())
{
 try
 {
  thread.sleep(50);
 }
 catch (interruptedexception e) {}
}

  显然这种办法和使用join方法相比,会浪费cpu资源,同时也会浪费一些等待时间,因为当前线程每隔一段时间去查询timer线程是否还存活,可能在timer线程已经结束了,但是当前线程还是要等待一段时间才能去监测它。

  关于volatile

  我们知道,在java中设置变量值的操作,除了long和double类型的变量外都是原子操作,也就是说,对于变量值的简单读写操作没有必要进行同步。这在jvm 1.2之前,java的内存模型实现总是从主存读取变量,是不需要进行特别的注意的。而随着jvm的成熟和优化,现在在多线程环境下volatile关键字的使用变得非常重要。在当前的java内存模型下,线程可以把变量保存在本地内存(比如机器的寄存器)中,而不是直接在主存中进行读写。这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量值的拷贝,造成数据的不一致。要解决这个问题,只需要像在本程序中的这样,把该变量声明为volatile(不稳定的)即可,这就指示jvm,这个变量是不稳定的,每次使用它都到主存中进行读取。一般说来,多任务环境下各任务间共享的标志都应该加volatile修饰。

扫描关注微信公众号