Thread執行緒運行,類似OS中Process,哪裡不同請參考此文章,裡面說恐龍就是OS聖經本。((遭毆

大部分資訊相關的畢業生"可能"跟我一樣,畢業前只執行過"單執行緒"程式,但業界是執行"多執行緒"程式。

什麼是"多執行緒",以作業系統流程生命週期圖說明......

Diagram_of_Process_State.png

上廁所舉例:

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

程式參考資料:

Thread start()跟run()不同處

Oracle Java Thread

Oracle Java ForkJoinWorkerThread

Oracle Java Object

參考書為:Java SE 7 技術手冊 by 林信良


結果圖:

MoneyThread01.jpg

MoneyThread02.jpg

 

程式碼:

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();
         }
      }                    
   }
}


結果圖:

PlayerThread01.jpg

PlayerThread02.jpg

 

程式碼:

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()數字為最高,優先獲得資源,卻不一定第一名執行完畢

創作者介紹
創作者 o迷苓o 的頭像
o迷苓o

~米漿牛奶~

o迷苓o 發表在 痞客邦 留言(0) 人氣()