# Thread及Runnable執行緒

## 多開一個執行緒-extends Thread

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

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

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

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

## 多執行緒-implements Runnable

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

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

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

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

## 三P馬的賽馬範例

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

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

開個賽馬場囉～

```java
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()方法來等待結果。

```java
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執行緒才會結束。

## 賽馬排名

新增紀錄排名的集合

```java
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);
}
```

```java
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

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

同步方法：

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

```java
Wizard wiz1 = new Wizard();
Wizard wiz2 = new Wizard();
wiz1.start();
wiz2.start();
```

同步區塊：

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