情景导入
在程序执行的过程中,如果遇见for循环,一般情况下需要该循环结束后,程序才会开始执行下一条指令;而我们平时在使用电脑时却可以一边听音乐一边刷微博,而这,就是靠多线程来实现的。
专业名词解释
线程(thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务(以上解释来源于百度词条)。
举例分析
画小球一般方法:
public class Normal_Way extends JFrame{
public static void main(String[] agrs) {
new Normal_Way();
}
public Normal_Way() {
// TODO Auto-generated constructor stub
setTitle("普通圆圈");
setSize(800,600);
setDefaultCloseOperation(3);
setLocationRelativeTo(null);
setVisible(true);
Graphics g=getGraphics();
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
int x=e.getX();
int y=e.getY();
Oval oval=new Oval(g,x,y,Color.black);
}
});
}
}
public class Oval {
Graphics g;
int x;
int y;
Color color;
public Oval(Graphics g,int x,int y,Color color) {
// TODO Auto-generated constructor stub
this.g=g;
this.x=x;
this.y=y;
this.color=color;
for(int i=0;i<50;i++) {
try { //增大每次循环的时间间隔
Thread.sleep(40);
}catch (InterruptedException ex) {
ex.printStackTrace();
}
g.drawOval(x+5*i, y+5*i, 40, 40);//画圆圈,并改变圆圈的位置
}
}
}
程序运行结果如下:
程序虽然运行了三次,但是每一次绘制却是在上次图形画完之后再开始的,有没有办法在第一次绘制还未完成的时候就开始第二次图形的绘制呢?
当然可以!使用线程嘛~
实现线程的方法
实现线程的方式有两类,一类是有返回值的,一类是没有返回值的,这里介绍两种没有返回值的实现方式。
1 继承Thread类,重写run()方法
First_Try.java
public class First_Try extends JFrame{
public static void main(String[] args) {
First_Try ft1=new First_Try();
}
public void paint(Graphics g) {
super.paint(g);
}
public First_Try() {
setTitle("小球一");
setSize(800,600);
setDefaultCloseOperation(3);
setLocationRelativeTo(null);
setVisible(true);
Graphics g=this.getGraphics();
addMouseListener (new MouseAdapter() {
public void mousePressed(MouseEvent e){
int x=e.getX ();
int y=e.getY ();
Color color=Color.black;
RunBall ballRun1 = new RunBall (g,x,y,color);
ballRun1.start ();// 启动线程
}
});
}
}
RunBall.java
public class RunBall extends Thread{
Graphics g;
int x;
int y;
Color color;
//构造方法
public RunBall(Graphics g,int x,int y,Color color) {
this.g=g;
this.x=x;
this.y=y;
this.color=color;
}
//重写run()方法
public void run() {
for(int i=0;i<50;i++) {
try {
Thread.sleep(40);
}catch (InterruptedException ex) {
ex.printStackTrace();
}
g.setColor(color);
g.drawOval(x+5*i, y+5*i, 50, 50);
}
}
}
程序运行结果如下
单看图片可能和上个程序没啥区别,但是这一次是能在第一次图形还未绘制完成时就可以进行第二次图形的绘制,就相当于你在用手机刷微博的同时还能听音乐。
如果多创建几个线程会是什么效果呢?
这里通过改变画笔的颜色方便观察程序运行的过程。
我们在First_Try类中添加以下代码:
color=Color.red;
RunBall ballRun2 = new RunBall (g,x,y,color);
ballRun2.start ();// 启动线程
color=Color.blue;
RunBall ballRun3 = new RunBall (g,x,y,color);
ballRun3.start ();//启动线程
程序运行效果如下:
2实现Runable接口,重写run方法
Second_Try.java
public class Second_Try extends JFrame{
public static void main(String[] args) {
new Second_Try();
}
public Second_Try() {
// TODO Auto-generated constructor stub
setTitle("小球二");
setSize(800,600);
this.setDefaultCloseOperation(3);
this.setLocationRelativeTo(null);
this.setVisible(true);
Graphics g=this.getGraphics();
addMouseListener (new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
int x=e.getX();
int y=e.getY();
// g.setColor(Color.blue);
RunBall2 ball1=new RunBall2(g,x,y,Color.blue);
new Thread(ball1).start();;
// g.setColor(Color.red);
RunBall2 ball2=new RunBall2(g,x,y,Color.red);
new Thread(ball2).start();
// g.setColor(Color.yellow);
RunBall2 ball3=new RunBall2(g,x,y,Color.yellow);
new Thread(ball3).start();
}
});
}
public void paint(Graphics g) {
super.paint(g);
}
}
RunBall2.java
public class RunBall2 implements Runnable{
Graphics g;
int x;
int y;
Color color;
public RunBall2(Graphics g,int x,int y,Color color) {
// TODO Auto-generated constructor stub
this.g=g;
this.x=x;
this.y=y;
this.color=color;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<50;i++) {
try {
Thread.sleep(40);
}catch (InterruptedException ex) {
ex.printStackTrace();
}
g.setColor(color);
g.drawOval(x+5*i, y+5*i, 40, 40);
}
}
}
程序运行如下:
BUG解决
在实现线程的过程中可能会遇到颜色覆盖的问题。
请问以下程序能否实现上述效果:
public class Second_Try extends JFrame{
public static void main(String[] args) {
new Second_Try();
}
public Second_Try() {
// TODO Auto-generated constructor stub
setTitle("小球二");
setSize(800,600);
this.setDefaultCloseOperation(3);
this.setLocationRelativeTo(null);
this.setVisible(true);
Graphics g=this.getGraphics();
addMouseListener (new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
int x=e.getX();
int y=e.getY();
g.setColor(Color.blue);//新增
RunBall2 ball1=new RunBall2(g,x,y,Color.blue);
new Thread(ball1).start();;
g.setColor(Color.red);//新增
RunBall2 ball2=new RunBall2(g,x,y,Color.red);
new Thread(ball2).start();
g.setColor(Color.yellow);//新增
RunBall2 ball3=new RunBall2(g,x,y,Color.yellow);
new Thread(ball3).start();
}
});
}
public void paint(Graphics g) {
super.paint(g);
}
}
public class RunBall2 implements Runnable{
Graphics g;
int x;
int y;
Color color;
public RunBall2(Graphics g,int x,int y,Color color) {
// TODO Auto-generated constructor stub
this.g=g;
this.x=x;
this.y=y;
this.color=color;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<50;i++) {
try {
Thread.sleep(40);
}catch (InterruptedException ex) {
ex.printStackTrace();
}
//g.setColor(color);
g.drawOval(x+5*i, y+5*i, 40, 40);
}
}
}
程序依旧可以正常运行,但是并没有圆圈颜色交替的效果,这是因为Second_Try类中使用的始终是同一个画笔,而画笔最后的颜色设置成了yellow,覆盖了另外两种颜色,所以只有黄色圆圈。
程序运行结果如下 :
拓展
稍微改动以下重写的run()方法就可以绘制不同的好看有趣的图形了
米字
浪漫烟花
这个就留给读者自己思考吧~