沒有直接采用繼承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實例)的多個線程。