1. 程式人生 > >Java學習之道:多執行緒——讓小球動起來(一)

Java學習之道:多執行緒——讓小球動起來(一)

在講執行緒之前,我們先來談談程序。在我接觸電腦的一段時間後,開始發現當開啟工作管理員後,會有一個程序的顯示,下面的映像名稱裡有很多的可執行檔案。這些可執行檔案有的是系統預設的,有的是我們開啟的,他們都會佔用一定記憶體。
知道了程序,那麼什麼是執行緒呢?執行緒就是執行中程式的排程單位。
我們知道,以前我們寫的程式碼,程式都是從上往下進行,就是必須要執行完上一句才會執行下一句。我們稱這種為單執行緒的程式。那麼多執行緒就是指同時有多個單執行緒同時進行運作,比如我們今天要做的小球遊戲,
如果面板中有多個小球在運動,那麼我們就要建立多個小球物件,然後讓他們同時運動,但是如果按我們以前的方式,程式碼從上往下執行,那麼想控制多個小球顯然很困難,這時我們就要運用到多執行緒。

講了那麼多,多執行緒怎麼實現呢?
這裡有兩個方法,一個是繼承Thread類,一個是實現runnable介面。具體的應用我們在練習中體現。


練習:控制小球的移動,要求:1.小球不能超出邊框2.小球相互碰撞,進行反彈.

這個練習首先要求我們掌握基本介面,知道主介面繼承JPanel,重寫paint方法以儲存面板。然後建立小球類,寫出構造方法以及get,set方法,繼承執行緒類,重寫run方法。最關鍵的就是小球要在邊界處反彈,還有就是小球遇到其他的小球要發生碰撞。最後讓執行緒run起來~~~

首先我們做出小球介面:

Java程式碼  收藏程式碼
  1. public class BallFrame extends
     JPanel {  
  2.     // 例項化一個數組物件  
  3.     private Ball[] ball = new Ball[10];  
  4.     // 例項化一個隨機數物件  
  5.     private Random r = new Random();  
  6.     public static void main(String[] args) {  
  7.         // 例項化一個面板物件  
  8.         BallFrame bf = new BallFrame();  
  9.         // 呼叫initUI方法  
  10.         bf.initUI();  
  11.     }  
  12.     // 介面函式  
  13.     public void initUI() {  
  14.         JFrame jf = new JFrame();// 例項化面板物件  
  15.         jf.setSize(new Dimension(600600));// 設定面板大小  
  16.         jf.setResizable(false);// 設定不可調節大小  
  17.         jf.setDefaultCloseOperation(3);// 設定關閉按鈕  
  18.         jf.setLocationRelativeTo(null);// 設定窗體居中  
  19.         this.setBackground(Color.white);// 設定面板背景為白色  
  20.         jf.setVisible(true);// 設定窗體可見  
  21.         jf.add(this, BorderLayout.CENTER);// 將面板新增到窗體上  
  22.         for (int i = 0; i < ball.length; i++) {  
  23.             // 例項化每個小球物件  
  24.             ball[i] = new Ball(new Color(r.nextInt(255), r.nextInt(255),  
  25.                     r.nextInt(255)), r.nextInt(550), r.nextInt(550), 50,  
  26.                     r.nextInt(4) + 1, r.nextInt(4) + 1this, i);  
  27.         }  
  28.         for (int i = 0; i < ball.length; i++) {  
  29.             // 將每個小球執行緒執行起來  
  30.             ball[i].start();  
  31.         }  
  32.     }  
  33.     // 重寫paint方法  
  34.     public void paint(Graphics g) {  
  35.         // 呼叫父類的paint方法  
  36.         super.paint(g);  
  37.         for (int i = 0; i < ball.length; i++) {  
  38.             // 從ball中獲取顏色並設定  
  39.             g.setColor(ball[i].getcolor());  
  40.             // 畫出小球  
  41.             g.fillOval(ball[i].getX(), ball[i].getY(), ball[i].getRadiu(),  
  42.                     ball[i].getRadiu());  
  43.         }  
  44.         // 呼叫碰撞函式  
  45.         collision();  
  46.     }  
  47.     // 碰撞函式  
  48.     private void collision() {  
  49.         // 距離陣列,儲存兩小球間的距離  
  50.         double[][] dis = new double[ball.length][ball.length];  
  51.         for (int i = 0; i < ball.length; i++) {  
  52.             for (int j = 0; j < ball.length; j++) {  
  53.                 // 計算兩個小球間的距離  
  54.                 dis[i][j] = Math.sqrt(Math.pow(ball[i].getX() - ball[j].getX(),  
  55.                         2) + Math.pow(ball[i].getY() - ball[j].getY(), 2));  
  56.             }  
  57.         }  
  58.         for (int i = 0; i < ball.length; i++) {  
  59.             for (int j = i + 1; j < ball.length; j++) {  
  60.                 if (dis[i][j] < (ball[i].getRadiu() + ball[j].getRadiu()) / 2) {  
  61.                     int t;  
  62.                     // 交換小球x方向的速度  
  63.                     t = ball[i].getVx();  
  64.                     ball[i].setVx(ball[j].getVx());  
  65.                     ball[j].setVx(t);  
  66.                     // 交換小球y方向的速度  
  67.                     t = ball[i].getVy();  
  68.                     ball[i].setVy(ball[j].getVy());  
  69.                     ball[j].setVy(t);  
  70.                     // 確定碰撞後第二個小球的位置  
  71.                     int x2 = ball[j].getX() - ball[i].getX(), y2 = ball[j]  
  72.                             .getY() - ball[i].getY();  
  73.                     ball[j].setX(ball[i].getX() + x2);  
  74.                     ball[j].setY(ball[j].getY() + y2);  
  75.                 } else {  
  76.                 }  
  77.             }  
  78.         }  
  79.     }  
  80. }  

然後我們建立執行緒物件Ball繼承Thread:

Java程式碼  收藏程式碼
  1. public class Ball extends Thread {  
  2.     // 初始化一些物件名  
  3.     private Color color;  
  4.     private int x, y, radiu, vx, vy;  
  5.     private BallFrame bf;  
  6.     private int id;  
  7.     /** 
  8.      * 建構函式 
  9.      *  
  10.      * @param color小球顏色 
  11.      * @param x小球橫座標 
  12.      * @param y小球縱座標 
  13.      * @param radiu小球直徑 
  14.      * @param vx小球橫向速度 
  15.      * @param vy小球縱向速度 
  16.      * @param bf面板 
  17.      * @param id標誌 
  18.      */  
  19.     public Ball(Color color, int x, int y, int radiu, int vx, int vy,  
  20.             BallFrame bf, int id) {  
  21.         this.color = color;  
  22.         this.x = x;  
  23.         this.y = y;  
  24.         this.radiu = radiu;  
  25.         this.vx = vx;  
  26.         this.vy = vy;  
  27.         this.bf = bf;  
  28.         this.id = id;  
  29.     }  
  30.     // 重寫run方法  
  31.     public void run() {  
  32.         super.run();// 呼叫父類run方法  
  33.         // 執行無限迴圈  
  34.         while (true) {  
  35.             // System.out.println("第"+id+"個球的x:"+x +"   y:"+y);  
  36.             x += vx;// 改變x的速度  
  37.             y += vy;// 改變y的速度  
  38.             // 如果x越界  
  39.             if (x <= 0 || x + radiu >= bf.getWidth()) {  
  40.                 vx = -vx;// x速度反向  
  41.                 if (x < 0)  
  42.                     x = 0;  
  43.                 else if (x > bf.getWidth() - radiu)  
  44.                     x = bf.getWidth() - radiu;  
  45.                 else {  
  46.                 }  
  47.             }  
  48.             // 如果y越界  
  49.             else if (y <= 0 || y + radiu >= bf.getHeight()) {  
  50.                 vy = -vy;// y速度反向  
  51.                 if (y < 0)  
  52.                     y = 0;  
  53.                 else if (y > bf.getHeight() - radiu)  
  54.                     y = bf.getHeight() - radiu;  
  55.                 else {  
  56.                 }  
  57.             } else {  
  58.             }  
  59.             try {  
  60.                 Thread.sleep(10);// 設定睡眠時間為10ms  
  61.             } catch (InterruptedException e) {  
  62.                 e.printStackTrace();  
  63.             }  
  64.             // 重繪  
  65.             bf.repaint();  
  66.         }  
  67.     }  
  68.     public Color getcolor() {  
  69.         return color;  
  70.     }  
  71.     public void setcolor(Color color) {  
  72.         this.color = color;  
  73.     }  
  74.     public int getX() {  
  75.         return x;  
  76.     }  
  77.     public void setX(int x) {  
  78.         this.x = x;  
  79.     }  
  80.     public int getY() {  
  81.         return y;  
  82.     }  
  83.     public void setY(int y) {  
  84.         this.y = y;  
  85.     }  
  86.     public int getRadiu() {  
  87.         return radiu;  
  88.     }  
  89.     public void setRadiu(int radiu) {  
  90.         this.radiu = radiu;  
  91.     }  
  92.     public int getVx() {  
  93.         return vx;  
  94.     }  
  95.     public void setVx(int vx) {  
  96.         this.vx = vx;  
  97.     }  
  98.     public int getVy() {  
  99.         return vy;  
  100.     }  
  101.     public void setVy(int vy) {  
  102.         this.vy = vy;  
  103.     }  
  104. }  

這樣我們的小球就run起來了~~