多線程的意義:
線程是依托于進(jìn)程而存在的,至于線程與進(jìn)程的區(qū)別在于,進(jìn)程屬于資源分配的單位,而線程則是作業(yè)調(diào)度的單位;進(jìn)程擁有自己的地址空間,而多個(gè)線程擁有自己的堆棧和局部變量,并共享所依托于進(jìn)程的資源。多進(jìn)程操作的意義在于多個(gè)進(jìn)程輪流共享CPU的時(shí)間片(針對(duì)單處理器情形,多處理器可理解為并行),屬于并發(fā)操作。多線程的并發(fā)操作優(yōu)勢在于當(dāng)程序遇到阻塞的情形。
當(dāng)程序的某個(gè)任務(wù)因外部條件問題,導(dǎo)致阻塞,如果沒有并發(fā),則整個(gè)程序停止,直到外部條件發(fā)生變化,使用并發(fā)后,程序中的其他任務(wù)還可以繼續(xù)執(zhí)行,如果沒有阻塞,在單處理器上考慮多線程并發(fā)也就沒有意義了,線程之間的切換會(huì)造成大量的時(shí)間消耗。
Java中三種多線程的啟動(dòng)方式
- 繼承Thread類,重寫run方法
public class HelloRunnable implements Runnable {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}
- 實(shí)現(xiàn)Runable接口,重寫run方法
public class HelloThread extends Thread {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new HelloThread()).start();
}
}
關(guān)于的不同在于Java語言本身只支持單繼承的局限性,利用Runable接口,當(dāng)子類已經(jīng)繼承與其他類,仍可以實(shí)現(xiàn)Runable接口進(jìn)行多線程操作。然而,從Runable接口和Thread類的源碼角度分析,Thread類實(shí)現(xiàn)了Runable接口,并且定義了更多用戶線程管理的方法,因此,可控性和功能會(huì)更豐富一點(diǎn)。
無論采用哪種方式,都必須將實(shí)例傳給new Thread()對(duì)象,然后調(diào)用start()的方法,使線程進(jìn)入就緒態(tài),等待CPU空閑才可執(zhí)行。
參考文檔
- 利用Callable和Future
對(duì)于上面兩種實(shí)現(xiàn)多線程的方式,父線程均無法獲取子線程的返回值,針對(duì)這一問題,我們下面介紹第三種實(shí)現(xiàn)多線程的方式,可以從子線程中獲取返回值。
class CallableThread implements Callable<String>{
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
return Thread.currentThread().getName();
}
}
ExecutorService executor = Executors.newFixedThreadPool(10);
List<Future<String>> list = new ArrayList<Future<String>>();
Callable<String> callable = new CallableThread();
for(int i =0;i<100;i++){
//使用submit方法調(diào)用call方法,并且返回Future對(duì)象
Future<String> future = executor.submit(callable);
list.add(future);
}
for (Future<String> future : list) {
try {
//get方法會(huì)阻塞,直到準(zhǔn)備結(jié)果就緒,在調(diào)用get方法前,可以先用isDone檢測是否執(zhí)行完畢。
System.out.println(new Date()+"::"+future.get());
} catch (InterruptedException | ExecutionException e) {
// TODO: handle exception
e.printStackTrace();
}
}
executor.shutdown();
Callable是一個(gè)具有類型參數(shù)的泛型,表示call方法的返回值,也就是函數(shù)執(zhí)行體(類似于run),并返回一個(gè)Future對(duì)象,而且,call方法要通過ExecutorService.submit調(diào)用。
這里,可以想想,這個(gè)機(jī)制是否和回調(diào)有點(diǎn)相似。
以上就是Java多線程的三種實(shí)現(xiàn)方式,僅此作為自己的學(xué)習(xí)記錄。