Java學習之道:多執行緒——讓小球動起來(一)
阿新 • • 發佈:2019-01-25
在講執行緒之前,我們先來談談程序。在我接觸電腦的一段時間後,開始發現當開啟工作管理員後,會有一個程序的顯示,下面的映像名稱裡有很多的可執行檔案。這些可執行檔案有的是系統預設的,有的是我們開啟的,他們都會佔用一定記憶體。
知道了程序,那麼什麼是執行緒呢?執行緒就是執行中程式的排程單位。
我們知道,以前我們寫的程式碼,程式都是從上往下進行,就是必須要執行完上一句才會執行下一句。我們稱這種為單執行緒的程式。那麼多執行緒就是指同時有多個單執行緒同時進行運作,比如我們今天要做的小球遊戲,
如果面板中有多個小球在運動,那麼我們就要建立多個小球物件,然後讓他們同時運動,但是如果按我們以前的方式,程式碼從上往下執行,那麼想控制多個小球顯然很困難,這時我們就要運用到多執行緒。
講了那麼多,多執行緒怎麼實現呢?
這裡有兩個方法,一個是繼承Thread類,一個是實現runnable介面。具體的應用我們在練習中體現。
練習:控制小球的移動,要求:1.小球不能超出邊框2.小球相互碰撞,進行反彈.
這個練習首先要求我們掌握基本介面,知道主介面繼承JPanel,重寫paint方法以儲存面板。然後建立小球類,寫出構造方法以及get,set方法,繼承執行緒類,重寫run方法。最關鍵的就是小球要在邊界處反彈,還有就是小球遇到其他的小球要發生碰撞。最後讓執行緒run起來~~~
首先我們做出小球介面:
Java程式碼-
public class BallFrame extends
- // 例項化一個數組物件
- private Ball[] ball = new Ball[10];
- // 例項化一個隨機數物件
- private Random r = new Random();
- public static void main(String[] args) {
- // 例項化一個面板物件
- BallFrame bf = new BallFrame();
- // 呼叫initUI方法
- bf.initUI();
- }
-
// 介面函式
- public void initUI() {
- JFrame jf = new JFrame();// 例項化面板物件
- jf.setSize(new Dimension(600, 600));// 設定面板大小
- jf.setResizable(false);// 設定不可調節大小
- jf.setDefaultCloseOperation(3);// 設定關閉按鈕
- jf.setLocationRelativeTo(null);// 設定窗體居中
- this.setBackground(Color.white);// 設定面板背景為白色
- jf.setVisible(true);// 設定窗體可見
- jf.add(this, BorderLayout.CENTER);// 將面板新增到窗體上
- for (int i = 0; i < ball.length; i++) {
- // 例項化每個小球物件
- ball[i] = new Ball(new Color(r.nextInt(255), r.nextInt(255),
- r.nextInt(255)), r.nextInt(550), r.nextInt(550), 50,
- r.nextInt(4) + 1, r.nextInt(4) + 1, this, i);
- }
- for (int i = 0; i < ball.length; i++) {
- // 將每個小球執行緒執行起來
- ball[i].start();
- }
- }
- // 重寫paint方法
- public void paint(Graphics g) {
- // 呼叫父類的paint方法
- super.paint(g);
- for (int i = 0; i < ball.length; i++) {
- // 從ball中獲取顏色並設定
- g.setColor(ball[i].getcolor());
- // 畫出小球
- g.fillOval(ball[i].getX(), ball[i].getY(), ball[i].getRadiu(),
- ball[i].getRadiu());
- }
- // 呼叫碰撞函式
- collision();
- }
- // 碰撞函式
- private void collision() {
- // 距離陣列,儲存兩小球間的距離
- double[][] dis = new double[ball.length][ball.length];
- for (int i = 0; i < ball.length; i++) {
- for (int j = 0; j < ball.length; j++) {
- // 計算兩個小球間的距離
- dis[i][j] = Math.sqrt(Math.pow(ball[i].getX() - ball[j].getX(),
- 2) + Math.pow(ball[i].getY() - ball[j].getY(), 2));
- }
- }
- for (int i = 0; i < ball.length; i++) {
- for (int j = i + 1; j < ball.length; j++) {
- if (dis[i][j] < (ball[i].getRadiu() + ball[j].getRadiu()) / 2) {
- int t;
- // 交換小球x方向的速度
- t = ball[i].getVx();
- ball[i].setVx(ball[j].getVx());
- ball[j].setVx(t);
- // 交換小球y方向的速度
- t = ball[i].getVy();
- ball[i].setVy(ball[j].getVy());
- ball[j].setVy(t);
- // 確定碰撞後第二個小球的位置
- int x2 = ball[j].getX() - ball[i].getX(), y2 = ball[j]
- .getY() - ball[i].getY();
- ball[j].setX(ball[i].getX() + x2);
- ball[j].setY(ball[j].getY() + y2);
- } else {
- }
- }
- }
- }
- }
然後我們建立執行緒物件Ball繼承Thread:
Java程式碼- public class Ball extends Thread {
- // 初始化一些物件名
- private Color color;
- private int x, y, radiu, vx, vy;
- private BallFrame bf;
- private int id;
- /**
- * 建構函式
- *
- * @param color小球顏色
- * @param x小球橫座標
- * @param y小球縱座標
- * @param radiu小球直徑
- * @param vx小球橫向速度
- * @param vy小球縱向速度
- * @param bf面板
- * @param id標誌
- */
- public Ball(Color color, int x, int y, int radiu, int vx, int vy,
- BallFrame bf, int id) {
- this.color = color;
- this.x = x;
- this.y = y;
- this.radiu = radiu;
- this.vx = vx;
- this.vy = vy;
- this.bf = bf;
- this.id = id;
- }
- // 重寫run方法
- public void run() {
- super.run();// 呼叫父類run方法
- // 執行無限迴圈
- while (true) {
- // System.out.println("第"+id+"個球的x:"+x +" y:"+y);
- x += vx;// 改變x的速度
- y += vy;// 改變y的速度
- // 如果x越界
- if (x <= 0 || x + radiu >= bf.getWidth()) {
- vx = -vx;// x速度反向
- if (x < 0)
- x = 0;
- else if (x > bf.getWidth() - radiu)
- x = bf.getWidth() - radiu;
- else {
- }
- }
- // 如果y越界
- else if (y <= 0 || y + radiu >= bf.getHeight()) {
- vy = -vy;// y速度反向
- if (y < 0)
- y = 0;
- else if (y > bf.getHeight() - radiu)
- y = bf.getHeight() - radiu;
- else {
- }
- } else {
- }
- try {
- Thread.sleep(10);// 設定睡眠時間為10ms
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- // 重繪
- bf.repaint();
- }
- }
- public Color getcolor() {
- return color;
- }
- public void setcolor(Color color) {
- this.color = color;
- }
- public int getX() {
- return x;
- }
- public void setX(int x) {
- this.x = x;
- }
- public int getY() {
- return y;
- }
- public void setY(int y) {
- this.y = y;
- }
- public int getRadiu() {
- return radiu;
- }
- public void setRadiu(int radiu) {
- this.radiu = radiu;
- }
- public int getVx() {
- return vx;
- }
- public void setVx(int vx) {
- this.vx = vx;
- }
- public int getVy() {
- return vy;
- }
- public void setVy(int vy) {
- this.vy = vy;
- }
- }
這樣我們的小球就run起來了~~