㈠ 如何創建線程如何保證線程安全
創建線程的方式一:繼承Thread類(由於java單繼承的特性,這種方式用的比較少)
步驟:
1、繼承Thread類,然後重寫run方法
2、創建實現類對象、代理類對象,然後代理類對象調用start()方法啟動線程
用實現Runnable介面的方式,實現多線程:
《模擬搶票系統》,代碼如下:
線程調用了start()方法,並不意味著立即執行,而是到就緒狀態,等待cpu的調度,所以每次執行的結果都是不一樣的。
創建線程的方式三:實現java.util.concurrent並發包下的Callable介面(進階版,初學者做個了解)
步驟:
1、創建一個類實現Callable介面,然後重寫call()方法
(和run方法不一樣的是,call方法可以有返回值,並且可以拋出異常)
2、創建Callable的實現類對象--》創建執行服務--》提交執行服務得到Future對象--》獲取結果--》停止服務
㈡ java Future 阻塞
有區別。比如你要查3次,每次分別耗時1s,2s,3s,用單線程,這個線程就會阻塞3次,總共耗時等於這3次查詢的總耗時,是6s;而如果用了3個線程來查,每個線程都用Future 的get方法來返回數據,這樣就是3個阻塞發生在同一時間,前兩個完成了會繼續等待第三個查詢完成,最終耗時是時間最長的那個查詢,是3s。
㈢ java future函數的作用
在並發編程時,一般使用runnable,然後扔給線程池完事,這種情況下不需要線程的結果。
所以run的返回值是void類型。
如果是一個多線程協作程序,比如菲波拉切數列,1,1,2,3,5,8...使用多線程來計算。
但後者需要前者的結果,就需要用callable介面了。
callable用法和runnable一樣,只不過調用的是call方法,該方法有一個泛型返回值類型,你可以任意指定。
線程是屬於非同步計算模型,所以你不可能直接從別的線程中得到函數返回值。
這時候,Future就出場了。Futrue可以監視目標線程調用call的情況,當你調用Future的get()方法以獲得結果時,當前線程就開始阻塞,直接call方法結束返回結果。
㈣ java中怎樣得到線程結束的通知
runnable 現成結束不通知,但是 run方法運行到最後一行就算結束了。
Callable 也可是實現通知。
MyCallable task2 = new MyCallable(1);
MyCallable task3 = new MyCallable(2);
MyCallable task1 = new MyCallable(0);
// 創建一個執行任務的服務
ExecutorService es = Executors.newFixedThreadPool(3);
// 提交並執行任務,任務啟動時返回了一個Future對象,
// 如果想得到任務執行的結果或者是異常可對這個Future對象進行操作
Future future1 = es.submit(task1);
// 獲得第一個任務的結果,如果調用get方法,當前線程會等待任務執行完畢後才往下執行
System.out.println("task1: " + future1.get());
Future future2 = es.submit(task2);
// 等待5秒後,再停止第二個任務。因為第二個任務進行的是無限循環
Thread.sleep(5000);
System.out.println("task2 cancel: " + future2.cancel(true));
// 獲取第三個任務的輸出,因為執行第三個任務會引起異常
// 所以下面的語句將引起異常的拋出
Future future3 = es.submit(task3);
System.out.println("task3: " + future3.get());
㈤ java協程和futuretask的區別
Callable要採用ExecutorSevice的submit方法提交,返回Future對象,通過Future的get()方法,同步拿到線程的返回結果,實例代碼如下:
public class ThreadExample12 { public static void main(String[] args) {
ExecutorService threadPool = Executors.newSingleThreadExecutor();
Future<String> future = threadPool.submit(new Callable<String>() { public String call() throws Exception {
Thread.sleep(2000); return "Hello World";
};
});
System.out.println("等待結果"); try {
System.out.println("返回結果為:" + future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Future取得的結果類型和Callable返回的結果類型必須一致,這是通過泛型來實現的。Callable要採用ExecutorSevice的submit方法提交,返回的Future對象可以取消任務,通過調用Future的future.cancel(true)方法實現,Future對象還可以對超時線程進行關閉,通過future.wait(3);如果線程耗時超過3秒則拋出異常
在這里有人可能會有疑問,既然要同步返回結果,那我為什麼要再開一個線程去執行呢,還不如直接在主線程執行就好。但是這種是局限於在一個線程時,如果需要同時執行多個線程,等待多個線程返回結果時,在主線程中是不能實現這種功能的。可以看一下實例代碼,就能明白了:
public class ThreadExample13 { public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(10);
CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool); for (int i = 1; i <= 10; i++) {
final int seq = i;
completionService.submit(new Callable<Integer>() {
@Override public Integer call() throws Exception {
Thread.sleep(new Random().nextInt(5000)); return seq;
}
});
} for (int i = 0; i < 10; i++) { try {
System.out.println(completionService.take().get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}