# 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); ```