2010/01/13

Java Concurrency(7)

接下來的範例我們結合一些先前說的概念,SimpleTreads包含了兩個threads,第一個主threads是每個Java應用
程式都擁有的,主thread製造一個新的thread從Runnable物件,MessageLoop,然後等待他直到結束,如果
MessageLoop thread花太多時間完成他的工作,main thread會中斷他

MessageLoop thread印出一系列的message,如果在他已經印出所有訊息之前中斷,MessageLoop thread印出一個訊息然後離開。

public class SimpleThreads {

    //Display a message, preceded by the name of the current thread
    static void threadMessage(String message) {
        String threadName = Thread.currentThread().getName();
        System.out.format("%s: %s%n", threadName, message);
    }

    private static class MessageLoop implements Runnable {
        public void run() {
            String importantInfo[] = {
                "Mares eat oats",
                "Does eat oats",
                "Little lambs eat ivy",
                "A kid will eat ivy too"
            };
            try {
                for (int i = 0; i < importantInfo.length; i++) {
                    //Pause for 4 seconds
                    Thread.sleep(4000);
                    //Print a message
                    threadMessage(importantInfo[i]);
                }
            } catch (InterruptedException e) {
                threadMessage("I wasn't done!");
            }
        }
    }

    public static void main(String args[]) throws InterruptedException {


        //Delay, in milliseconds before we interrupt MessageLoop
        //thread (default one hour).
        long patience = 1000 * 60 * 60;

        //If command line argument present, gives patience in seconds.
        if (args.length > 0) {
            try {
                patience = Long.parseLong(args[0]) * 1000;
            } catch (NumberFormatException e) {
                System.err.println("Argument must be an integer.");
                System.exit(1);
            }

        }

        threadMessage("Starting MessageLoop thread");
        long startTime = System.currentTimeMillis();
        Thread t = new Thread(new MessageLoop());
        t.start();

        threadMessage("Waiting for MessageLoop thread to finish");
        //loop until MessageLoop thread exits
        while (t.isAlive()) {
            threadMessage("Still waiting...");
            //Wait maximum of 1 second for MessageLoop thread to
            //finish.
            t.join(1000);
            if (((System.currentTimeMillis() - startTime) > patience) &&
                    t.isAlive()) {
                threadMessage("Tired of waiting!");
                t.interrupt();
                //Shouldn't be long now -- wait indefinitely
                t.join();
            }

        }
        threadMessage("Finally!");
    }
}

輸出結果

main: Starting MessageLoop thread
main: Waiting for MessageLoop thread to finish
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
Thread-0: Mares eat oats
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
Thread-0: Does eat oats
.
.可以嘗試將patience改變,改小一點就會發現Tired of waiting的訊息被傳出來在中斷MessageLoop的時候。

main thread不斷的測試t thread是否存活,並印出Waiting的字樣,然後給予t thread一秒的時間去完成他的事情,直到這一秒一秒累積起來超過了main thread的耐心之後,main thread便會先發出"tired of waiting"的訊息後將t thread中斷掉,t知道自己被interrupt掉之後就發出了InterruptedException,發出"I wasn't done"的訊息然後直接輸出Finally字樣。

可能有人會好奇interrupt方法後面為什麼又要發出join,直覺可能認為是interrupt之後就想要強迫他把剩下內容全部都輸出,不過其實這裡有個盲點,如果在interrupt後面打上一行程式碼

System.out.println(t.getState());

會發現其實這個thread已經terminate了!這時後再給他下join指令其實是一點意義都沒有的,所以可以把join跟interrupt兩行到過來,這樣子就能強迫在thread terminate前把內容輸出了,這樣一來不是更符合沒有耐心的感覺嘛?(笑)

參考網址
http://java.sun.com/docs/books/tutorial/essential/concurrency/simple.html

No comments:

Post a Comment