總網頁瀏覽量

2013年3月6日 星期三

執行緒

定義:程式碼同時進行數個處理流程。

啟動執行緒:增加程式中的處理流程。

優點:讓程式更有效率進行處理,例如進行要花費N鐘頭的迴圈處理時,可以別的執行緒進行其他處理。

注意:Thread一旦run結束或中斷,就再也無法呼叫start()重新啟動thread



1.執行緒實作方法有三種:
第一、extends Thread建立Thread的子類別obj1


Thread子類別建立物件後,呼叫start()(obj1.start())由Thread繼承而來)啟動執行緒,之後跑run()裡面的程式。如此一來可以分別建立物件,每個物件可以有自己執行緒。




第二、宣告類別obj並且implement Runnable,宣告執行緒類別,以obj為引數建立執行緒物件。

class CTest implements Runnable{
public run(){.....}}

public static main(String args[]){

CTest obj = new CTest();
CTest obj2 =new CTest();

Thread t1 = new Thread(obj);//產生執行緒物件
Thread t2 =new Thread(obj2);
t1.start();
t2.start();

}

第三、使用匿名內部類別




以上必須override run() method。
run()裡面的東西就是新處理流程的起點。

可以利用sleep(1000)暫時停止執行緒,這是暫停一秒。




class multi_thread implements Runnable{//實作thread第一步,implements Runnable

    @Override
    public void run() {//第二步改寫run(),
      for(int i=1;i<=10;i++){
      System.out.print("i="+i);//執行緒在這裡可能被插隊
     System.out.println("name="+Thread.currentThread().getName());

            try {
                Thread.sleep(1500);//可以用Thread.sleep();讓執行緒進入blocked狀態(休息)
1500表示1.5秒,.sleep必須寫例外處理否則不給編譯過。
            } catch (InterruptedException ex) {            
            }            }  
}}

public class runnable {
  public static void main(String[] args)  {
     
            multi_thread obj = new multi_thread();
            Thread thread1 = new Thread(obj,"Taiwan");//建立執行緒,thread1去跑obj的程式,並且將thread1的名稱命名為Taiwan
            Thread thread2 = new Thread(obj,"Formosa");
         
            thread1.setPriority(Thread.MIN_PRIORITY);//thread權限,括號裡面是int型態
            thread2.setPriority(Thread.MAX_PRIORITY);
           
            thread1.start();//啟動thread
            thread2.start();
         
        try{  
            thread1.join();//.join()必須跟try-catch或throws InterruptedException配合
//thread1執行緒結束才會繼續執行try-catch之外的程式
            thread2.join();//thread2執行緒執行完之後才會執行下面的程式
        }catch(InterruptedException ex){}
        System.out.println("finished");
          }  
}



同步synchronized
執行緒存取變數或物件時將資料lock住,禁止其他執行緒進行存取。

使用時機:多個執行緒在同一時間存取同一個變數或物件


避免資料不一致、插隊情形,避免互相等待造成死結。

常常與notify() wait()配合
notify():通知waiting狀態的執行緒,如果有多個thread則隨意喚醒其中一個

wait():執行去進入waiting狀態,必須等待其他執行緒呼叫notify()才能將它喚醒


以下是沒有synchronized的程式碼以及執行結果
某家公司有兩個司機,位公司開車賺錢,宣告company類別管理這兩名司機賺來的錢,兩名司機賺的錢交回公司。

class Company{
    private int sum = 0;

    public void add(int a){//若要正確結果,在這邊加上synchronized修飾
    int tmp = sum;
    System.out.println("目前合計金額"+tmp+"dollars");
    System.out.println("賺到"+a);
    tmp=tmp+a;
    System.out.println("合計金額是"+tmp+"dollars");
    sum=tmp;
    }
}
class Driver implements Runnable{
    private Company comp;
    public Driver(Company c){
            comp=c;
    }
    @Override
    public void run(){
    for(int i=0;i<3;i++)
    {
     System.out.println(Thread.currentThread().getName());//列印執行緒名字
        comp.add(50);
    }
}       
}

public class synchron2 {
    public static void main(String[] args) {
        Company cmp = new Company();
        Driver drv1= new Driver(cmp);
        Thread thread1 = new Thread(drv1);
        thread1.start();
       
       
        Driver drv2=new Driver(cmp);
        Thread thread2 = new Thread(drv2);
        thread2.start();
    }
}


執行結果:

Thread-0
目前合計金額 0dollars
賺到50
合計金額是50dollars
Thread-1
Thread-0
目前合計金額 50dollars  //Thread1與Thread0幾乎同時讀取資料  
目前合計金額 50dollars //這裡可以看到Thread1讀取到Thread0改過後的資料
賺到50
賺到50
合計金額是100dollars
Thread-0
目前合計金額100dollars
合計金額是100dollars
Thread-1
賺到50
目前合計金額100dollars
賺到50
合計金額是150dollars
合計金額是150dollars
Thread-1
目前合計金額150dollars
賺到50
合計金額是200dollars             //正確金額應該是300元

沒有留言:

張貼留言