多線程使用:模擬一次宇宙戰爭來,看看多線程的其中一種使用場景。
第一步(使用Runnable)
第一步,通過Runnable構建一個軍隊的線程,軍隊發動多次進攻,線程線程執行完便是軍隊戰爭結束
把控戰爭進度通過控制while循環實現
/**
* @author liuzonghua
* @Package top.maniy.util
* @Description:
* @date 2018/11/7 16:22
*/
public class ArmyRunnable implements Runnable{
//volatile保證了線程可以正確的讀取其他線程寫入的值
//可見性 JMM happens-before原型
volatile boolean keepRunning=true;
@Override
public void run() {
while (keepRunning){
for(int i=0;i<5;i++) {
System.out.println(Thread.currentThread().getName() + "進攻對方【" + i + "】");
//讓出了處理時間,下次該誰進攻還不一定呢!
Thread.yield();
}
}
System.out.println(Thread.currentThread().getName()+"結束了戰鬥!");
}
}
第二步(Thread)
Runnable使用了,我們在使用一次Thread,來表示一個關鍵人物介紹這場戰爭
public class KeyPersonThread extends Thread{
@Override
public void run(){
System.out.println(Thread.currentThread().getName()+"開始了戰鬥!");
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"釋放奧義");
}
System.out.println(Thread.currentThread().getName()+"結束戰鬥");
}
}
第三步(戰爭舞臺)
我們要把這些軍隊和關鍵人物搬上舞臺來跑起來。
也就是線程的使用,這裏可以把舞臺也通過線程實現,便是線程調用線程的場景。
改變keepRunning 值來停止戰爭
public class Stage extends Thread {
@Override
public void run(){
System.out.println("歡迎觀看多線程模擬宇宙戰爭");
//等待幾秒吧
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("開始了");
ArmyRunnable armyRunnableOne =new ArmyRunnable();
ArmyRunnable armyRunnableTwo =new ArmyRunnable();
//使用Runnable接口創建線程
Thread armyOne = new Thread(armyRunnableOne,"弗利沙軍隊");
Thread armyTwo = new Thread(armyRunnableTwo,"白鬍子第一軍隊");
//啓動線程,讓軍隊開始作戰
armyOne.start();
armyTwo.start();
//舞臺線程休眠,大家專心觀看軍隊廝殺
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("雙方停止戰鬥吧");
armyRunnableOne.keepRunning =false;
armyRunnableTwo.keepRunning=false;
try {
armyOne.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("激戰之中,出現boss");
Thread boss =new KeyPersonThread();
boss.setName("奧利哈剛的巨神兵");
System.out.println("我要結束一切");
armyRunnableOne.keepRunning =false;
armyRunnableTwo.keepRunning=false;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
boss.start();
try {
boss.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("一切將會結束");
System.out.println("宇宙戰爭結束");
}
public static void main(String[] args){
new Stage().start();
}
}
知識點
一、volatile關鍵字
一旦一個共享變量(類的成員變量、類的靜態成員變量)被volatile修飾之後,那麼就具備了兩層語義:
1)保證了不同線程對這個變量進行操作時的可見性,即一個線程修改了某個變量的值,這新值對其他線程來說是立即可見的。
2)禁止進行指令重排序。
二、Thread.yield();
當調用Thread.yield()方法時,會給線程調度器一個當前線程願意讓出CPU使用的暗示,但是線程調度器可能會忽略這個暗示.
說白話,就是線程暫停允許執行其他線程(包括自己),我把球丟在空中,大家一起搶。
三、t.join();
t.join()方法會使所有線程都暫停並等待t的執行完畢。這裏等待軍隊線程結束後,在執行關鍵人物線程。