在corejava的課程中,有一個重要的知識點,就是線程。 java
那什麼是線程呢?線程,是「進程」中某個單一順序的控制流。而進程和流程的最大區別就在於,每一個進程都會獨享一塊存儲區域,多個線程只能共享此進程的這塊存儲區域。 dom
那線程會給咱們的java程序帶來什麼好處呢?好處一,能夠實現並行,好處二,能夠更有效的利用資源。 學習
下面咱們就編寫一個小小的賽跑遊戲來看看線程給咱們程序帶來的驚喜吧。 this
首先,我們先看看程序最後完成的效果,及操做流程: spa
遊戲一開始將直接進入主題,簡潔的界面,無需說明文檔,一眼便知如何操做。(見圖1)
線程
圖1:遊戲一開始的界面 對象
選擇好咱們要支持的運動員後,點擊肯定按鈕,此時遊戲尚未開始,但咱們已不可再改變支持的對象了。(見圖2) 繼承
圖2:下注後的界面 接口
好吧,既然不能更改,那麼就讓比賽快點開始吧!「蝸牛,加油!加油!」(見圖3) 遊戲
圖3:遊戲開始後的界面
哦也!蝸牛贏了!看到了嗎,結果就在圖4裏,哈哈哈,點擊肯定後,400分就拿到手了!
圖4: 出結果後的界面
真是一場痛快的比賽!
如今,我們來進行一下賽後分析,上面這個小遊戲究竟有多少個線程呢?我聽到有人說「這個很容易就看出來了,一共就3個嗎,每一個參賽的跑者,都是一個線程」。真的只是表面看到的這樣嗎?
這個程序一共有5個線程!
不信嗎?那聽我來講說:第1個線程,就是被你們忽略了,卻有很是熟悉的main。這個是咱們java 程序運行時,一定會運行的,也是咱們學習java時最先接觸的一個線程。第2、3、4個 線程,就是你們說的,那三個賽跑者,每個都是一個獨立的線程。第5個線程,從圖上是看不到的,卻又是一個很是重要的線程,它甘居幕後,擔任着發令,裁決輸贏的任務,咱們暫且把它叫作「裁判」吧。
整個遊戲的過程咱們瞭解了,所包含的線程咱們也都分析了,下面的時間就是着手實現的階段了:
打着MVC的旗號,項目結構成了下面這個樣子:
images:中放置着,程序所須要的所有圖片
vo:裏放着咱們的一個實體類
enter:裏存放着程序的入口
view:裏存放着程序的界面
control裏存放着「裁判」類和監聽器。
界面部分的編寫我就不細說了,就是要繼承JFrame來定義咱們本身的窗體。順便說一句,那個跑道是經過畫圖繪製的背景。別忘了給按鈕添加監聽器哦!
今天的主題是線程,那麼咱們就要仔細看看線程的代碼了:
java中實現線程的有兩種途徑,一種是繼承Thread類,還有一種是實現Runnable接口。下面的關於 「運動員」、」裁判」的實現,我都統一使用了第二種方法,就是實現Runnable接口。具體代碼以下:
package saipao.vo;
import java.awt.Image; import java.awt.Point; import java.util.Random;
import javax.swing.ImageIcon;
public class Runners implements private private private private private private private /* * 名稱、座標、圖片,小圖標是隻讀的,只有get方法 * */
public return } public this.flag } public return } public return } public return } public return }
public this.win }
public return } public this.isRun } public super(); this.name this.weiZhi=new this.imgBig=new this.imgSmall=new this.isRun=true;
}
//退到起點 public this.weiZhi.move(0, this.flag=this.win=false; this.isRun=true; } //是否押對了 public return }
public Random while(this.isRun){ int x+=rd.nextInt(10)+1; this.weiZhi.move(x,(int)this.weiZhi.getY()); try Thread.sleep(100); } // e.printStackTrace(); } }
}
} |
好了,運動員的代碼咱們看到了,你發現了Runnable接口中聲明瞭幾個方法了嗎? 答對了,就一個叫作Run的方法。當線程啓動後,就將會執行Run方法中的代碼。知道執行完畢退出run方法,此線程就死亡了。
光有運動員,沒有裁判怎麼行!
package saipao.control;
import java.util.Vector;
import javax.swing.JOptionPane;
import saipao.view.MainFrame; import saipao.vo.Runners;
/* * 裁判類,用來肯定是否有到達終點的賽跑者 * */ public class CaiPan implements Thread [] thread; MainFrame mf; public super(); this.vt this.width this.mf=mf; }
//運動員開始跑
//判斷是否有人到達重點 public //調用開跑方法 this.startRun(); //判斷是否有運動員到達終點 while(vt.get(0).isRun()){ mf.lblWeiZhi(); for(int int if(x>=this.width){ vt.get(i).setWin(true);//設置當前運動員贏了 //並通知全部運動員都不用再跑了 for(int vt.get(j).setRun(false); } //退出判斷是否到達終點的循環 break; } } } //賽跑結束,判斷是輸仍是贏,並計算金額 boolean for(int if(vt.get(i).isWiner()){ flag=vt.get(i).isWiner(); break; } } if(flag){ JOptionPane.showMessageDialog(mf,
}else{ JOptionPane.showMessageDialog(mf, } mf.changeMoney(flag); mf.btnKongZhi(2, }
} |
有沒有注意到,Runnable接口僅僅是提供了線程啓動後要調用的功能(run),並無提供啓動線程的功能。要想真正的使線程運行起來,仍是要經過Thread的幫助,由於Thread類中提供了啓動線程的start()功能。
剩下的就是在對應的監聽事件中,命令咱們的裁判發號施令,開始咱們的比賽了。
在和你們說byebye以前,還想請你們思考一下,運動員(Runners)那個類除了經過實現Runnable接口來編寫線程程序,還有沒有別的方式,使其成爲線程?若是有,那麼會不會影響咱們其餘類的代碼呢?
當即動手吧!我會一直期待着你的答案哦!
做者:中軟卓越天津ETC