---
# System prepended metadata

title: Thread/Timer
tags: [Java]

---

# Thread

(Thread中文可以叫做: 執行續/線程)

目前上面寫過的程式, 都是單執行續, 意思是這個process同時只會做一件事
但其實可以同時有多個Thread, 同時(並發)執行。
    
Thread有一些static方法,
```
Thread currentThread(); 取得當前執行的thread
void sleep(long); 當前thread休眠一段時間(毫秒)
```
範例:
```java=
public class Main {
    public static void main(String[] args) {
        Thread t = Thread.currentThread();
        System.out.println(t.getName()); //main
        Thread.sleep(1000);
        System.out.println(t.isAlive()); //true
    }
}
```

假設我們想要在**背景** 輸出1~5, 每次輸出delay 1秒
用這種正常寫法是沒辦法達成的, 永遠會先一行一行慢慢執行
```java=
public static void main(String[] args) {
    for (int i = 1; i <= 5; i++) {
         Thread.sleep(1000);
         System.out.println(i);
    }
    System.out.println("Hello World!");
}
```
## 創造Thread
執行Thread的時候, 是呼叫Thread裡面的run()方法
    
Thread某幾段原始碼如下:
```java=
public class Thread implements Runnable {
                                         
    private Runnable target;
                                         
    //a few hundred lines
    
    public Thread(Runnable target) { //constructor
        //constructor contents...
    }
    
    //a few hundred lines
    
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
    
    //a few hundred lines
}                                        
```
這時候有兩種方法可以創造有run()值行的thread
                                         
### 1. Override Thread#run()
standard override                
```java=
class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 1; i <= 5; i++) {
            Thread.sleep(1000);
            System.out.println(i);
        }
    }
}

// ---------- main ----------
MyThread t = new MyThread();
```
anonymous
```java=
// ---------- main ----------
Thread t = new Thread() {
    @Override
    public void run() {
        for (int i = 1; i <= 5; i++) {
            Thread.sleep(1000);
            System.out.println(i);
        }
    } 
};
```
### 2. Create target Runnable
    
```java=
// ---------- runnable implementation ----------
class YourRunnable implements Runnable {
    @Override
    public void run() {
        //...
    }
}
// ---------- main ----------                        
Thread t = new Thread(new YourRunnable());
```
anonymous
```java=
Runnable r = new Runnable({
    @Override
    public void run() {
        //...
    }
};
// ---------- main ----------                        
Thread t = new Thread(r);
```
lambda:
```java=
Runnable r = () -> {
    @Override
    public void run() {
        //...
    }
};
// ---------- main ----------                        
Thread t = new Thread(r);
```
lambda, 但直接放入參數中:
```java=
// ---------- main ----------                        
Thread t = new Thread(() -> {
    @Override
    public void run() {
        //...
    }
});
```
                                         
## 執行thread
```java=
Thread#start();
```

```java=
Thread thread = new Thread(r);
thread.start(); //啟動Thread
System.out.println(thread.isActive()); //true, 因為此時thread確實在背景執行
                                         
/*
true
1
2
3
4
5
*/
```
**注意, 啟動thread是呼叫```start()```,不是```run()```**
run()純粹是執行Runnable裡面的```run()```, 會直接把main thread sleep掉!
```java=
Thread thread = new Thread(r);
thread.run(); //直接在main thread 呼叫runnable, 並沒有啟動thread
System.out.println(thread.isAlive()); //false, 因為thread從未被啟動
                                        
/*
1
2
3
4
5
false
*/
```
## 終止thread 
```java=
Thread#interrupt();
```
假設我們想要在Runnable裡面直接終止Thread:
```java=
@Override
public void run() {
    try {
        for (int i = 1; i <= 5; i++) {
            Thread.sleep(1000);
            System.out.println(i);
            if (i == 3) {
                return; //直接結束run()
            }
        }
    } catch (InterruptedException ex) {
          ex.printStackTrace();
    }
};
//>
```
# Timer
Java Timer能讓你把task放進Timer的TaskQueue, 並且可以選擇:
1. ```schedule(task,delay)```延遲delay ms後開始,
2. ```schedule(task,delay,period)```延遲delay ms後開始, 並且每period ms執行一次

除了```schedule```, 還有一個叫做```scheduleAtFixedRate```
```schedule```會因為被系統其他因素(如GC)延遲 而延遲下一次任務
```scheduleAtFixedRate```如果被延遲, 他會把未執行的任務做完
        
1000ms後, 執行一次run()
```java==
Timer t = new Timer();

TimerTask task = new TimerTask() {
    @Override
    public void run() {
        System.out.println("hello");
    }
};
t.schedule(task,1000);
```

2000ms後, 每1000ms執行一次run()
```java==
Timer t = new Timer();

TimerTask task = new TimerTask() {
    @Override
    public void run() {
        System.out.println("hello");
    }
};
t.schedule(task,2000,1000);
```