2017年2月27日 星期一

啟動 Thread 時的注意事項 (Thread 一)

※main方法也是Thread

public static void main(String... a) {
    System.out.println(Thread.currentThread().getName()); // main
    System.out.println("Thread數量=" + Thread.activeCount()); // 1
}




※Thread名稱

public class ThreadTest1 extends Thread {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
    
    // public void start() {
    // System.out.println("Start method");
    // }
    
    public static void main(String... a) {
        new ThreadTest1().start();
        new ThreadTest1().run();
    }
}

※直接呼叫 run() 的Thread名稱是main;呼叫 start() 的 Thread 預設名稱是 Thread-0
其實是「Thread-」加數字,以上面的例子,如果將 main 裡的 start() 和 run() 互換,
就會變成 main 和 Thread-1,因為它知道有 main Thread 了

※如果不喜歡Thread-數字的名稱,可以用如下的方法修改
ThreadTest1 t1 = new ThreadTest1();
t1.setName("xxx");
t1.start();
這樣子名稱就變成xxx了

※註解的 start() 打開後,main 的start() 就不會呼叫 run()了,因為Thread 的 start() 方法是
public synchronized void start()
所以變成覆寫,當然參數不同沒有關係
而如果將覆寫的回傳值改成其他的也會編譯錯誤

※start() 只能呼叫一次,超過會出「java.lang.IllegalThreadStateException」的錯



※Thread.activeCount只是估計值

public class ThreadTest1 extends Thread {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
    
    public static void main(String... a) {
        new ThreadTest1().start();
        new ThreadTest1().start();
        new ThreadTest1().run();
        new ThreadTest1().run();
        System.out.println("Thread數量=" + Thread.activeCount());
    }
}

※Thread.activeCount()不一定會顯示正確的結果,如start()才是真正的Thread;而呼叫run()就不是,所以以這個例子是一個main Thread + 2個Start(),所以應該是3個
但多執行幾次,數字有可能變成2,甚至是1
因為run()方法裡一下子就執行完了,執行完了Thread 也就消失了,所以start寫在Thread.acdtiveCount() 的上一行
如果寫在 run() 方法裡也是會有類似的情形



※ run 和 start的不同

public class ThreadTest1 extends Thread {
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            String threadName = Thread.currentThread().getName();
            System.out.println(threadName + "執行了" + i + "次");
        }
    }
    
    public static void main(String... a) {
        // new ThreadTest1().start();
        // new ThreadTest1().start();
        new ThreadTest1().run();
        new ThreadTest1().run();
    }
}

※結果:
main執行了1次
main執行了2次
main執行了3次
...
main執行了100次
main執行了1次
main執行了2次
main執行了3次
...
main執行了100次

※如果將 start() 註解打開, run() 註解,會得到類似以下的結果
...
Thread-0執行了21次
Thread-1執行了1次
Thread-0執行了22次
Thread-1執行了2次
Thread-0執行了23次
Thread-1執行了3次
Thread-1執行了4次
Thread-1執行了5次
...

這才是正確的結果,Thread 要互相交互



※無限迴圈

public class ThreadTest extends Thread {
    @Override
    public void run() {
        int i = 1;
        for (;;) {
            System.out.println(i);
            ++i;
        }
    }
    
    public static void main(String... a) {
        Thread t = new Thread(new ThreadTest());
        t.setDaemon(true);
        t.start();
    
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

※如果不使用 setDaemon(true),將會無限迴圈
但如果使用 setDaemon(true),可以讓 main 執行完時,呼叫setDaemon(true) 的 Thread 也結束
一定要在 start() 之前呼叫


沒有留言:

張貼留言