线程小球
首先,什么是线程?线程是程序中一个单一的顺序控制流程。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程。线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。
每一个java程序都至少有一个线程,这个线程称为主线程。当一个java程序启动时,JVM会创建主线程,并在该线程中调用main()方法。也就是我们通常说的主函数是程序的入口。线程可以理解为“程序内部的一个独立的运行单位”。我们通常写的java程序大多数
是单线程程序,也称为顺序编程。程序通过主线程入口进入之后然后按顺序执行下去,然后结束程序。
这里所说的线程小球,不是通常的单线程程序,而是多线程程序。那什么又是多线程程序呢?多个进程的内部是完全独立的,而多线程是共享一块内存空间和一组系统资源(在同一进程内),在程序内部可以互相调用。
废话不多先说,看看怎么来实现线程小球,让多个小球在我们的窗体上动起来吧。Java中多线程的实现,有两种方法,第一可以继承Thread类实现,第二可以实现Runnable接口创建线程。这两种方法都要重写它的run()方法。
下面我以第一种方法为例说明:
首先新建一个窗体类BallFrame:
public class BallFrame extends JFrame{
private static final long serialVersionUID = -1450872967753766027L;
public static void main(String[] args){
BallFrame bf=new BallFrame();
bf.initUI();
}
public void initUI(){
this.setTitle("线程小球");
this.setSize(400, 500);
this.setDefaultCloseOperation(3);
this.setLocationRelativeTo(null);
this.setVisible(true);
BallListener bl=new BallListener(this);//建立小球监听
this.addMouseListener(bl);//给窗体添加监听
}
}
然后建立监听类:BallListener:
public class BallListener extends MouseAdapter{
private Graphics2D g;
private BallFrame bf;
public BallListener(BallFrame bf){
this.bf=bf;
g=(Graphics2D)bf.getGraphics();//获取画笔
}
public void mousePressed(MouseEvent e) {
int x=e.getX();
int y=e.getY();
Ball ball=new Ball(x,y,g,bf);//建立小球对象,画小球
ball.start();//启动小球线程
}
}
最后需要建立一个小球类,主要思路就是通过鼠标监听每点击一次建立一个小球对象,然后每一个小球对象是一个子线程,所以当主线程结束之后,每一个小球作为一个独立的运行单元,可以不受主线程的影响,在窗体中独立的运行:
public class Ball extends Thread{
private Graphics2D g;
private int x,y;
private BallFrame bf;
public Ball(int x,int y,Graphics2D g,BallFrame bf){//通过构造函数将画笔、窗体 和坐标传过来
this.x=x;
this.y=y;
this.bf=bf;
this.g=g;
}
@SuppressWarnings("static-access")
public void run(){//重写Thread的run()方法
while(y<bf.getHeight()+25){
g.setColor(bf.getBackground());
g.fillOval(x-26, y-26, 52, 52);
y++;//将纵坐标递加,使小向下落,当然也可以通过将x、y坐标不同的处理使小球往不同方向移动
g.setColor(Color.black);
g.fillOval(x-25, y-25, 50, 50);
try {
this.sleep(42);//线程执行得太快,需要使线程休眠一下,42毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
(通过这种方法画出的小球会出现一闪一闪的情况,笔者这个需要慢慢改进。。。)