Given the code fragments:



class Caller implements Callable<String> {

    String str;

    public Caller(String s) {
        this.str = s;
    }

    public String call() throws Exception {
        return str.concat(" Caller");
    }
}

class Runner implements Runnable {

    String str;

    public Runner(String s) {
        this.str = s;
    }

    public void run() {
        System.out.println(str.concat(" Runner"));
    }
}

and

public static void main(String[] args) throws InterruptedException, ExecutionException {
    ExecutorService es = Executors.newFixedThreadPool(2);
    Future f1 = es.submit(new Caller("Call"));
    Future f2 = es.submit(new Runner("Run"));
    String str1 = (String) f1.get();
    String str2 = (String) f2.get();//line n1
    System.out.println(str1 + " : " + str2);
}

What is the result?

A. The program prints:

Run Runner
Call Caller : null

And the program does not terminate.
B. The program terminates after printing:

Run Runner
Call Caller : Run

C. A compilation error occurs at line n1.
D. An Execution is thrown at run time.

題解

程式第52行,會建立最多可以擁有兩個執行緒的ExecutorService。

程式第53行,會建立Caller物件,並使用新的執行緒去執行Caller物件的call方法。

程式第54行,會建立Runnable物件,並使用新的執行緒去執行Runnable物件的run方法。

程式第55行,會等待呼叫Caller物件的call方法的執行緒是否已經執行完畢,接著回傳call方法的回傳值。

程式第56行,會等待呼叫Runnable物件的run方法的執行緒是否已經執行完畢,接著回傳null。

在程式第54行至56行之間,某條ExecutorService的執行緒會執行到Runnable物件的run方法內的第23行,輸出「Run Runner」。

程式第57行,輸出「Call Caller : null」。