浅谈多线程
多线程即实现程序内部的多个任务的同时执行。
1.线程的定义:
每个运行的程序都是一个进程。一个进程中包含多个线程。所以线程也可以说是一个微小的进程。它是进程的再次细分。可以这么说,如果把进程比喻成一个大的执行任务,那个线程就是这个大任务中一个个细小的小任务。要执行一进程,必须一步步实现单个的线程。线程是在一个进程中独立的控制流,即程序内部的控制流。
2.单线程与多线程
单线程:只有一条线程的进程称为单线程。
多线程:有不止一个线程的进程称为多线程。一个进程内部不同的线程可以同时执行,所以多线程也叫并发线程。
3. 开启多线程的优点和缺点
优点:
(a)提高程序响应速度。使用线程可以把占据时间长的程序中的任务放到后台去处理。
(b) 充分利用系统资源,提高效率。使用线程可以减少CPU的内存消耗。CPU不需要等到这个任务结束后才去执行其他任务。而是在执行这个任务的同时,利用空闲时间与空间去实现其他任务。大大减少了时间消耗。
缺点:
(a)使用过多线程效率可能反而降低。这是因为操作系统需要在大量线程之间切换,切换所带来的时间消耗可能大于了使用线程所减少的时间消耗。
(b)可能消耗更多的内存空间。更多的线程也意味着需要更多的内存空间来执行进程。
但是,相比较而言,使用多线程的优势在大多数情况下远胜过劣势的。所以现在的项目开发中,多线程编程技术得到了广泛的应用。
4. 多线程的实现途径
Java语言提供了三种实现方式:
(a) 继承Thread类
(b)实现Runnable接口
(c) 使用Timer和TimerTask组合
下面将以继承Thread类来讲诉多进程的实现。
以下代码是以实现在画面上添加运动的小球为例:
Game类:
主要实现界面的初始化创建和创建线程对象
public class Game {
private JFrame jf;
public void showUI(){
jf = new JFrame();
jf.setTitle("运动小球");
jf.setSize(500,500);
jf.setDefaultCloseOperation(3);
jf.setLocationRelativeTo(null);
jf.setLayout(new FlowLayout());
JButton btn = new JButton("添加小球");
btn.addActionListener(listener);
//将按钮添加到面板上,防止小球经过面板时,按钮被擦除
JPanel jp = new JPanel();
jp.setPreferredSize(new Dimension(500,40));
jp.setLayout(new FlowLayout(FlowLayout.CENTER,0,0));
EmptyBorder border = new EmptyBorder(5, 5, 5, 5); //设置按钮间的间距
jp.add(btn);
jf.add(jp);
jf.setVisible(true);
}
//创建动作监听类
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//创建一个线程对象
Ball t = new Ball(jf);
//启动线程,只能调用一个start方法
t.start();
}
};
public static void main(String[] args) {
Game g = new Game();
g.showUI();
}
}
Ball类:
创建一个类,继承Thread,以实现进程的创建。
//创建进程类
public class Ball extends Thread {
private JFrame jf;
private Graphics g;
//定义圆心的坐标
private int x,y;
//定义圆的半径
private int radius=30;
//水平方向的速度
private int vx = 3;
//垂直方向的速度
private int vy = 1;
public Ball (JFrame jf){
this.jf = jf;
g = jf.getGraphics();
}
//重写父类的run方法
public void run(){
while(true){
try {
//让线程休眠
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//只清除自己的小球
g.setColor(jf.getBackground());
g.fillOval(x-radius,y-radius, 2*radius, 2*radius);
//变化圆心坐标
x+=vx;
y+=vy;
//当小球越界时
if(x>=jf.getWidth()-radius){
vx=-Math.abs(vx);
}
if(x<=radius){
vx=Math.abs(vx);
}
if(y>=jf.getHeight()-radius){
vy=-Math.abs(vy);
}
if(y<=radius){
vy=Math.abs(vy);
}
//在圆心出画圆
g.setColor(Color.green);
g.fillOval(x-radius,y-radius, 2*radius, 2*radius);
}
}
}
总结:以继承Thread类来实现线程时,首先需要创建一个类来继承Thread,然后重写父类的run方法。在run方法中写入你希望运行进程时,程序需要出现的效果。当需要使用进程时,应该创建一个进程类的对象,用该对象调用start方法,那么此时程序自动执行进程对象中run方法中的代码。可创建多个进程对象,实现多个进程的同时运行。这个例子中,每一个运动的小球就是一个进程,添加多个小球,就是添加多个进程,多个小球可以同时运动,它们之前没有相互影响,不需要等一个小球运动完之后,才可以添加另一个小球,这便是多进程的实现。