Thread及Runnable執行緒

多開一個執行緒-extends Thread

若只要多開一個執行緒,繼承Thread就可以了。要執行的功能放在run()方法內。

public class Horse extends Thread {
    @Override
    public void run(){
        ...
    }
}

要使用此Thread物件,就new出實例來

Horse horse = new Horse();
horse.start();

多執行緒-implements Runnable

若需要多個執行緒,就實作Runnable介面。同樣的,執行功能放在run()方法。

public class HorseRunnable implements Runnable {
    @Override
    public void run(){
        ...
    }
}

若要使用Runnable物件,需要先new出Runnable物件,再用此物件產生Thread物件。

HorseRunnable horseRunnable = new HorseRunnable();
Thread thr = new Thread(horseRunnable);
thr.start();

三P馬的賽馬範例

目前有三匹馬,分別是三個執行緒,而main執行緒主要負責計算賽馬名次。

public class Horse extends Thread {
    @Override
    public void run(){
        try{
            //延遲2秒
            sleep(2000);
            //getName()可以取得執行緒名稱
            System.out.println(getName() + "到達");
        }catch(InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}

開個賽馬場囉~

public class Racing{
    Horse h1 = new Horse();
    Horse h2 = new Horse();
    Horse h3 = new Horse();
    
    h1.setName("h1");
    h2.setName("h2");
    h3.setName("h3");
    
    h1.start();
    h2.start();
    h3.start();
}

最後發現main執行緒會比其他三匹馬更早結束,為了讓main(裁判)等待三匹馬完成,使用join()方法來等待結果。

public class Racing{
    Horse h1 = new Horse();
    Horse h2 = new Horse();
    Horse h3 = new Horse();
    
    h1.setName("h1");
    h2.setName("h2");
    h3.setName("h3");
    
    h1.start();
    h2.start();
    h3.start();
    
    try{
        h1.join();
        h2.join();
        h3.join();
    }
    catch(InterruptedException e)
    {
        e.printStackTrace();
    }
    System.out.println("執行緒結束");
}

如此一來便會等待馬匹跑完以後,main執行緒才會結束。

賽馬排名

新增紀錄排名的集合

public class Racing{
    //增加紀錄排名的集合
    List<RankHorse> rank = new ArrayList();
    Horse h1 = new Horse();
    Horse h2 = new Horse();
    Horse h3 = new Horse();
    
    h1.setName("h1");
    h2.setName("h2");
    h3.setName("h3");
    
    h1.start();
    h2.start();
    h3.start();
    
    try{
        h1.join();
        h2.join();
        h3.join();
    }
    catch(InterruptedException e)
    {
        e.printStackTrace();
    }
    System.out.println("執行緒結束");
    System.out.println(rank);
}
public class RankHorse extends Thread {
    private List<RankHorse> rank;
    
    //傳入排名集合
    public RankHorse(List<RankHorse> rank){
        this.rank = rank;
    }
    
    @Override
    public void run(){
        try{
            //延遲2秒
            sleep(2000);
            //getName()可以取得執行緒名稱
            System.out.println(getName() + "到達");
            
            //加入集合
            rank.add(this);
        }catch(InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}

yield()和sleep()會暫停目前工作,進入等待隊列(Queue)

資源鎖定synchronized

限制同一時間只能有一個執行緒執行該方法,可以透過同步方法或同步區塊達成。

同步方法:

public class Wizard extends Thread{
    public void run(){
       thunder(); 
    }
    
    //規定一次只能有一個人使用打雷
    public synchronized void thunder(){
       System.out.println("THUNDER!!");
    }
}
Wizard wiz1 = new Wizard();
Wizard wiz2 = new Wizard();
wiz1.start();
wiz2.start();

同步區塊:

public class Wizard extends Thread{
    public void run(){
       synchronized(this){
          thunder(); 
       }
    }
    
    
    //規定一次只能有一個人使用打雷
    public void thunder(){
       System.out.println("THUNDER!!");
    }
}

Last updated