Thread執行緒運行,類似OS中Process,哪裡不同請參考此文章,裡面說恐龍就是OS聖經本。((遭毆
大部分資訊相關的畢業生"可能"跟我一樣,畢業前只執行過"單執行緒"程式,但業界是執行"多執行緒"程式。
什麼是"多執行緒",以作業系統流程生命週期圖說明......
上廁所舉例:
new狀態: 人群閒逛的聚集點
admitted: 有繳10元的A、B、C,同意進入ready狀態
ready狀態: 有A、B、C想上廁所
scheduler dispatch: 指揮者發現B繳20元,先讓他進入running狀態
running狀態: B在廁所中
I/O or event wait: 指揮者限制5分鐘上完廁所,B還沒上完就被迫回到waiting狀態
waiting狀態: B等待中
I/O or event completion: 指揮者叫B如果還想上需回到ready狀態
running狀態: A在廁所中
interrupt: 廁所突然大爆炸,A還沒上完被迫回到ready狀態
running狀態: 廁所修好了,指揮者給C先上廁所
exit: C上完廁所
terminated狀態: C回到人群中
Java當然有這些狀態,例如...
Thread-start(): ready狀態,等排班決定哪個執行緒能進入running狀態
Thread-interrupt(): running狀態回到ready狀態
Object-wait(): waiting狀態,等待沒有執行緒進入running狀態
Object-notify(): scheduler dispatch,如果沒人進入running狀態就能使用
Thread-run(): 根據呼叫run()方法的執行緒(就是Main)執行,但會失去多執行緒意義
Thread-sleep(): 暫停執行緒N毫秒,1000毫秒等於1秒
個人做兩個程式,一個是觀察執行緒們執行過程,另個是執行緒們跟Scanner比速度。
圖片參考資料:OS Process LifeCycle
程式參考資料:
Oracle Java ForkJoinWorkerThread
參考書為:Java SE 7 技術手冊 by 林信良
結果圖:
程式碼:
import java.util.concurrent.ForkJoinWorkerThread;
class Transaction implements Runnable
{
private long tTimeS,tTimeE;
private String tNo;
private int tMoney;
private String act[]={"deposit","withdraw"};//存款/提款
private int aFlag = -1;
Transaction(String tNo,int tMoney,int aFlag)
{setTra(tNo,tMoney,aFlag);}
//synchronized是Lock功能,在多執行緒中需存入資料只能一個
private synchronized void setTra(String tNo,int tMoney,int aFlag)
{
this.tNo=tNo;
this.tMoney=tMoney;
this.aFlag=aFlag;
}
private String getNo(){return tNo;}
private int getMoney(){return tMoney;}
private int getAct(){return aFlag;}
//Thread run() Override
public void run()
{
tTimeS = System.currentTimeMillis();
System.out.println("Name:"+Thread.currentThread().getName()+" STime:"+tTimeS/1000.000);
System.out.println("交易號:"+getNo()+" 金額:"+getMoney()+" 行為:"+act[getAct()]);
try {
if(getAct()==1)//行為是提款的人
{
Thread.sleep(10000);//都要停10秒
System.out.println(Thread.currentThread().getName()+"睡覺了...");
}
}catch(InterruptedException e)
{System.out.println("中斷了...");}
tTimeE = System.currentTimeMillis();
System.out.println("Name:"+Thread.currentThread().getName()+" Time:"+(tTimeE-tTimeS)/1000.000+"秒");
}
}
class VIP implements Runnable
{
private long vTimeS,vTimeE;
private String tNo;
private double tMoney;
private double addPrice;
VIP(String tNo,double tMoney)
{System.out.println("call VIP():"+Thread.currentThread().getName());setVip(tNo,tMoney);}
private synchronized void setVip(String tNo,double tMoney)
{
this.tNo=tNo;
this.tMoney=tMoney;
}
private String getNo(){return tNo;}
private double getMoney(){return tMoney;}
//Thread run() Override
public void run()
{
vTimeS = System.currentTimeMillis();
System.out.println("Name:"+Thread.currentThread().getName()+" STime:"+vTimeS/1000.000);
for(int i=1;i<10000;i++)
{
addPrice += (getMoney()/15)*0.8;
}
System.out.println("交易號:"+getNo()+" 增加價錢:"+addPrice);
vTimeE = System.currentTimeMillis();
System.out.println("Name:"+Thread.currentThread().getName()+" Time:"+(vTimeE-vTimeS)/1000.000+"秒");
}
}
public class MoneyThread
{
public static void main(String args[])
{
for(int x=0;x<10;x++)
{
if(x==3)
{
VIP vip = new VIP("T"+Integer.toString(x),100000000);//1E dollars
Thread vipT = new Thread(vip);
//設定優先權,優先得到資源,但不會優先執行
vipT.setPriority(10);
vipT.start();
}
else
{
Transaction tra = new Transaction("T"+Integer.toString(x),((int)(Math.random()*1000)),((int)(Math.random()*9))%2);
Thread traT = new Thread(tra);
traT.setPriority(5);
traT.start();
}
}
}
}
結果圖:
程式碼:
import java.util.concurrent.ForkJoinWorkerThread;
import java.util.Scanner;
class Player implements Runnable
{
private long pTimeS,pTimeE;
private String pNo;
private int actFlag=-1;
private String act[]={"Right","Worse"};//答對/答錯
private int totalPoint=0;
Player(String pNo)
{setPlay(pNo);}
//synchronized是Lock功能,在多執行緒中需存入資料只能一個
private synchronized void setPlay(String pNo)
{this.pNo=pNo;}
private String getNo(){return pNo;}
//Thread run() Override
public void run()
{
pTimeS = System.currentTimeMillis();
System.out.println("Name:"+Thread.currentThread().getName()+" 玩家:"+getNo()+" STime:"+pTimeS/1000.000);
for(int i=0;i<10;i++)
{
actFlag=((int)(Math.random()*9))%2;
try {
if(actFlag==1)//猜錯的電腦
{
totalPoint-=10;
System.out.println(Thread.currentThread().getName()+":"+act[actFlag]+",要懲罰...");
Thread.sleep(5000);//都要停5秒
}
else totalPoint+=10;
}catch(InterruptedException e)
{System.out.println(Thread.currentThread().getName()+"玩家中斷連線了...");}
}
pTimeE = System.currentTimeMillis();
System.out.println("Name:"+Thread.currentThread().getName()+" Time:"+(pTimeE-pTimeS)/1000.000+"秒"+" Point:"+totalPoint);
}
}
class User implements Runnable
{
private long uTimeS,uTimeE;
private String uNo;
private String re="[0-1]";
private int uAct;
private String act[]={"Right","Worse"};//答對/答錯
private int totalPoint=0;
User(String uNo)
{setUser(uNo);}
private synchronized void setUser(String uNo)
{this.uNo=uNo;}
private String getNo(){return uNo;}
//Thread run() Override
public void run()
{
uTimeS = System.currentTimeMillis();
System.out.println("Name:"+Thread.currentThread().getName()+" 玩家:"+getNo()+" STime:"+uTimeS/1000.000);
for(int i=0;i<10;i++)
{
Scanner uSca = new Scanner(System.in);
System.out.print("輸入答案:");
uAct = uSca.nextInt();
try {
if(Integer.toString(uAct).matches(re))
{
if(uAct==1)//猜錯的玩家
{
totalPoint-=10;
System.out.println(Thread.currentThread().getName()+":"+act[uAct]+",要懲罰...");
Thread.sleep(2000);//都要停2秒
}
else totalPoint+=10;
}
else System.out.println("請輸入0或1!");
}catch(InterruptedException e)
{System.out.println(Thread.currentThread().getName()+"玩家中斷連線了...");}
}
uTimeE = System.currentTimeMillis();
System.out.println("Name:"+Thread.currentThread().getName()+" Time:"+(uTimeE-uTimeS)/1000.000+"秒"+" Point:"+totalPoint);
}
}
public class PlayerThread
{
public static void main(String args[])
{
for(int x=0;x<3;x++)
{
if(x==2)
{
User user = new User("U"+Integer.toString(x));
Thread userT = new Thread(user);
//設定優先權,優先得到資源,但不會優先執行
//userT.setPriority(10);
userT.start();
}
else
{
Player play = new Player("P"+Integer.toString(x));
Thread playT = new Thread(play);
//playT.setPriority(5);
playT.start();
}
}
}
}
結論:
1.從MoneyThread跟PlayerThread結果圖發現,執行緒們能運行run()要看排班老大心情!((啥
2.執行run()內容是分開,以結果圖的System.out.print可得知
3.從MoneyThread VIP(...)的System.out.print知道這時是Main Thread,除非到run()才是N Thread
VIP(String tNo,double tMoney)
{System.out.println("call VIP():"+Thread.currentThread().getName());setVip(tNo,tMoney);}
4.從PlayerThread結果圖發現,即使有Scanner但不會影響到其他Thread
5.即使設定setPriority()數字為最高,優先獲得資源,卻不一定第一名執行完畢