多线程入门总结

什么是线程
提到线程,首先要了解进程。每个程序都有一个入口,在程序运行时,系统首先从程序入口开始按语句的顺序执行,知道整个程序结束。简单的说进程就是程序在处理机中的一次运行,不仅包括程序代码,同时也包括执行指令所需的任何系统资源。线程是进程中的一个实体,是比进程单位更小的执行单位,与进程不同的时,它没有入口和出口,因此自身不能自动执行,是在某一进程中的,由进程触发执行。每个程序都至少有一个线程,即主线程。在单个程序中同时运行多个线程完成不同的工作,称为多线程。利用多线程同时完成不同的任务,可以节省很多时间。

线程与进程的区别
1.简单而言,一个应用程序就是一个进程,线程则是进程内部的多个运行单位。
2.多个进程内部数据和状态都是完全独立的,而线程是共享一块内存空间和一组系统资源,在程序内部可以互相调用;而进程间通信大多数情况是必须通过网络实现的。
3.线程本身的数据通常只有寄存器数据,以及一个程序执行时使用的堆栈,所以线程的切换比进程切换的负担要小。

继承Thread类实现多线程
在JAVA中,每个线程对象都是一个继承了java.util.Thread类的对象或implements了java.util.Runnable接口的类的对象,线程的启动是通过调用线程对象的start()方法启动的,线程运行是从线程对象的run方法开始,当run方法结束后,线程即运行结束。下面通过以继承Thread类,作简单的弹球游戏为例实现多线程。
首先要有一个窗体,在前面的总结中已经有了创建窗体的经验,这里不重述了,相关代码如下:
this.setTitle("弹球游戏");//设置窗体标题
this.setSize(500,600);//设置窗体大小
this.getContentPane().setBackground(Color.RED);//设置背景颜色


this.setLayout(new FlowLayout());//设置画布

JButton bt = new JButton("开始");//创建按钮对象

this.add(bt);//添加按钮

this.setDefaultCloseOperation(3);//点击关闭时退出窗体
this.setVisible(true);//将窗体显示在屏幕上

final Graphics g = this.getGraphics();//设置布局管理器
这些语句都是写在一个初始化窗体的方法内的。有了窗体之后,需要给按钮添加动作监听器,按一下“开始”按钮就能画圆,这里实现监听器接口就不要重新定义一个类了,直接在初始化窗体的方法内写一个匿名内部类就可以了,格式如下:
//匿名内部类,动作监听器
ActionListener atl = new ActionListener(){ };

实现监听器之后用bt.addActionListener(atl)这一句给按钮添加监听器,这个方法的完整代码如下:
/**
* 初始化窗体
*/
public void init(){
this.setTitle("弹球游戏");//设置窗体标题
this.setSize(500,600);//设置窗体大小
this.getContentPane().setBackground(Color.RED);//设置背景颜色


this.setLayout(new FlowLayout());//设置画布

JButton bt = new JButton("开始");//创建按钮对象

this.add(bt);//添加按钮

this.setDefaultCloseOperation(3);//点击关闭时退出窗体
this.setVisible(true);//将窗体显示在屏幕上

final Graphics g = this.getGraphics();//设置布局管理器


//匿名内部类,动作监听器
ActionListener atl = new ActionListener(){

public void actionPerformed(ActionEvent e){

}


};


bt.addActionListener(atl);//给按钮添加监听器

}
现在需要重新定义一个Ball类来实现画球,并且实现球的移动。首先我们要明白要实现球的移动就是在一个while循环中不停的画圆,在画之前首先要把先前画的擦除掉,就可以实现球的移动,擦除掉原先的球就是将圆重新画一遍,只不过颜色为窗体的背景色。具体代码如下:
//小球移动的方法
public void move() {

while(true){
//清除图像
g.setColor(blf.getContentPane().getBackground());
g.fillOval(x0,y0,30,30);

g.setColor(Color.BLUE);
g.fillOval(x0+=x,y0+=y,30,30);

}
现在可以实现多线程了,首先是Ball类要继承Thread类,然后要重写父类的public void run()方法,即调用move()方法,最后在匿名内部类里面创建Ball类的两个对象,并调用start()方法,就可以实现两个球在窗体里面移动了。具体代码如下:
public class Ball extends Thread{

java.util.Random rd = new java.util.Random();

private int x0=50,y0=50;
private int x,y;

private BallFrame blf;
Graphics g;

public Ball(BallFrame blf){
this.blf = blf;
g = blf.getGraphics();

//小球的初始位置
x0=rd.nextInt(300)+50;
y0=rd.nextInt(300)+50;

//小球的增量
x = rd.nextInt(50)-30;
y = rd.nextInt(50)-30;

}

//重写父类的方法
public void run(){
move();
}

//小球移动的方法
public void move() {

while(true){
//清除图像
g.setColor(blf.getContentPane().getBackground());
g.fillOval(x0,y0,30,30);
g.setColor(Color.BLUE);
g.fillOval(x0+=x,y0+=y,30,30);

}

try{
Thread.sleep(100);
}catch(Exception ep){
ep.printStackTrace();
}
}

}

}

匿名内部类重写的方法如下:
//匿名内部类,动作监听器
ActionListener atl = new ActionListener(){

public void actionPerformed(ActionEvent e){
Ball b = new Ball(BallFrame.this);
b.start();

Ball b1 = new Ball(BallFrame.this);
b1.start();

}


};
但是这样发现很多问题,比如球碰撞到四壁时没有弹回,两球相撞时也没有弹回等等,针对地一个问题,对球移动的方法的代码修改如下:
//小球移动的方法
public void move() {

while(true){
//清除图像
g.setColor(blf.getContentPane().getBackground());
g.fillOval(x0,y0,30,30);

if (x!=0){
if (x0<=8||x0>=480){//左右两壁
x=-x;
}else if (y0<=30||y0>=580){//上下两壁
y=-y;
}else if ((x0<=8&&y0<=30)||(x0<=8&&y0>=580)||(x0>=480&&y0<=30)||(x0>=480&&y0>=580)){//垂直碰撞四壁
x=-x;y=-y;
}

g.setColor(Color.BLUE);
g.fillOval(x0+=x,y0+=y,30,30);

}

try{
Thread.sleep(100);
}catch(Exception ep){
ep.printStackTrace();
}
}

}
运行之后的截图如下:


[img]http://dl.iteye.com/upload/attachment/528448/e1716ac8-b2ce-32d9-ba90-ca9dfc2dbae7.png[/img]


此弹球游戏还有许多问题,欢迎各位赐教!!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值