[英]Java: Using ExecutorService for concurrency
我想並行執行一些任務,所以我在 Java 中搜索多線程,我找到了這個類,ExecutorService。 我嘗試了一個簡單的例子,但我不確定它是否並行運行。
long startTime = System.currentTimeMillis();
List<Callable<String>> callables = new ArrayList<Callable<String>>();
ExecutorService executor = Executors.newCachedThreadPool();
callables.add(new Callable<String>() {
public String call() {
for (int i=0; i<100000; i++) {
System.out.println("i "+i);
}
return "Task 1";
}
}
);
callables.add(new Callable<String>() {
public String call() {
for (int j=0; j<100000; j++) {
System.out.println("j "+j);
}
return "Task 2";
}
}
);
callables.add(new Callable<String>() {
public String call() {
for (int k=0; k<100000; k++) {
System.out.println("k "+k);
}
return "Task 3";
}
}
);
try {
List<Future<String>> futureLst = executor.invokeAll(callables);
for (Future future : futureLst) {
try {
System.out.println(future.get());
} catch (ExecutionException e) {
e.printStackTrace();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
executor.shutdown();
System.out.println("Time Taken - "+ (System.currentTimeMillis() - startTime));
上面的代碼按預期工作正常並打印計數並返回字符串。 上述程序執行所需的時間為“3229”毫秒。
我把上面的程序改寫如下,
long startTime = System.currentTimeMillis();
for (int i=0; i<100000; i++) {
System.out.println("i "+i);
}
for (int j=0; j<100000; j++) {
System.out.println("j "+j);
}
for (int k=0; k<100000; k++) {
System.out.println("k "+k);
}
System.out.println("Time Taken - "+ (System.currentTimeMillis() - startTime));
這個程序花費的時間是“3104”毫秒,比並行執行編碼的時間少。
那么我在第一個程序中做錯了什么嗎? 我的第一個程序是否並行運行任務,因為我看到沒有線程花費的時間更少?
第一個是順序的,第二個是並行的——這很好。
看起來運行時間主要由System.out.println
調用中緩慢的控制台寫入操作組成(請參閱為什么 System.out.println 這么慢? )。
如果您改為寫入文件,您應該觀察不同的行為(和並行版本加速)。
您的任務主要是使用System.out.println
調用(即PrintStream.println
方法)寫入標准輸出。 它最終調用PrintStream.write
方法,其中主體已同步。 因此,您只是將時間浪費在創建線程和同步開銷上。 由於PrintStream
本質上是順序的,它不能並行輸出,所以當單個流正在寫入時,其他人只是在等待它。 某些操作可以像 for 循環和字符串和數字的連接一樣並行化,但它們比輸出到 stdout 快得多。
為了從並發中獲得額外的性能,您應該避免使用共享的順序資源。 在您的情況下,它是標准輸出流。
你的代碼是正確的。 結果是由於計算太簡單,運行速度太快。 大部分運行時間由控制台輸出的速度決定,因此多線程的好處並不能彌補設置和關閉線程池的開銷。 此外,try-catch 設置還增加了一個小的開銷(非常小,但足以在這個簡單的場景中糾結結果)。 --> 您可以嘗試增加循環大小(提示:使用靜態變量 MAX_LOOP 進行更快的測試),您將看到不同之處。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.