沒有直接採用繼承Thread類或者繼承Runnable的介面來實現多線程,而是使用了匿名內部類。
要匯入的類:
import javax.swing.*; import java.awt.*;
1.定義SowPanel類,繼承JPanel類,這個類有兩個整型數群組成員,用來儲存雪花起始位置。在建構函式中為數組賦初值;重寫父類的paint()方法;定義一個啟動多線程的startSnow()方法。
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對象,添加到視窗中。
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的運行效果是不同的,前者顯示的下雪情境總是有閃爍的感覺;後者則沒有閃爍,個人感覺後者效果更好些。
接下來我們來看個例子
這裡我們做一個完整的例子來說明線程產生的方式不同而產生的線程的區別:
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執行個體)的多個線程。