没有直接采用继承Thread类或者继承Runnable的接口来实现多线程,而是使用了匿名内部类。
要导入的类:
1
2
|
import javax.swing.*; import java.awt.*; |
1.定义SowPanel类,继承JPanel类,这个类有两个整型数组成员,用来保存雪花起始位置。在构造函数中为数组赋初值;重写父类的paint()方法;定义一个启动多线程的startSnow()方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
class SnowPanel extends JPanel { //定义整型数组,存储雪花坐标 private int [] x= new int [ 300 ]; private int [] y= new int [ 300 ]; public SnowPanel() { //设置背景为黑色 setBackground(Color.black); //用随机数初始化雪花坐标 for ( int i= 0 ;i<x.length;i++) { x[i]=( int )(Math.random()* 800 ); y[i]=( int )(Math.random()* 600 ); } } public void paint(Graphics g) { //继承父类画的方法 super .paint(g); //设置颜色为白色 g.setColor(Color.white); //利用循环画出多个雪花 for ( int i= 0 ;i<x.length;i++) { g.drawString( "*" ,x[i],y[i]); } } //定义一个方法启动多线程,并使用匿名内部类 public void startSnow() { new Thread() { public void run() { while ( true ) { for ( int i= 0 ;i<y.length;i++) { //坐标下移 y[i]++; //检查是否越界 if (y[i]== 600 ) y[i]= 0 ; //重绘 repaint(); } try { Thread.sleep( 10 ); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } } |
2.定义ShowFrame类,继承Jframe 类。在构造方法中设置窗口的显示属性,并创建ShowPanel对象,添加到窗口中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
class SnowPanel extends JPanel { //定义整型数组,存储雪花坐标 private int [] x= new int [ 300 ]; private int [] y= new int [ 300 ]; public SnowPanel() { //设置背景为黑色 setBackground(Color.black); //用随机数初始化雪花坐标 for ( int i= 0 ;i<x.length;i++) { x[i]=( int )(Math.random()* 800 ); y[i]=( int )(Math.random()* 600 ); } } public void paint(Graphics g) { //继承父类画的方法 super .paint(g); //设置颜色为白色 g.setColor(Color.white); //利用循环画出多个雪花 for ( int i= 0 ;i<x.length;i++) { g.drawString( "*" ,x[i],y[i]); } } //定义一个方法启动多线程,并使用匿名内部类 public void startSnow() { new Thread() { public void run() { while ( true ) { for ( int i= 0 ;i<y.length;i++) { //坐标下移 y[i]++; //检查是否越界 if (y[i]== 600 ) y[i]= 0 ; //重绘 repaint(); } try { Thread.sleep( 10 ); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } } |
3.运行效果图片(此为静态图):
疑问:发现其他的不改变,继承Frame、Panel和继承JFrame、Jpanel的运行效果是不同的,前者显示的下雪场景总是有闪烁的感觉;后者则没有闪烁,个人感觉后者效果更好些。
接下来我们来看个例子
这里我们做一个完整的例子来说明线程产生的方式不同而生成的线程的区别:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
package debug; import java.io.*; import java.lang.Thread; class MyThread extends Thread{ public int x = 0 ; public void run(){ System.out.println(++x); } } class R implements Runnable{ private int x = 0 ; public void run(){ System.out.println(++x); } } public class Test { public static void main(String[] args) throws Exception{ for ( int i= 0 ;i< 10 ;i++){ Thread t = new MyThread(); t.start(); } Thread.sleep( 10000 ); //让上面的线程运行完成 R r = new R(); for ( int i= 0 ;i< 10 ;i++){ Thread t = new Thread(r); t.start(); } } } |
上面10个线程对象产生的10个线程运行时打印了10次1。下面10个线程对象产生的10个线程运行时打印了1到10。我们把下面的10个线程称为同一实例(Runnable实例)的多个线程。