概念
進程:指一個內存中運行的應用程序,每個進程都有自己獨立的一塊內存空間,一個進程中可以啓動多個線程。比如在Windows系統中,一個運行的exe就是一個進程。
線程:指進程中的一個執行流程,一個進程中可以運行多個線程。比如java.exe進程中可以運行很多線程。線程總是屬於某個進程,進程中的多個線程共享進程的內存。
“同時”執行:是人的感覺,在線程之間實際上輪換執行。
Java中的線程
使用java.lang.Thread類或者java.lang.Runnable接口編寫代碼來定義、實例化和啓動新線程。
一個Java應用總是從main()方法開始運行,main()方法運行在一個線程內,它被稱爲主線程。
Java線程:創建與啓動
創建:擴展java.lang.Thread類,或實現java.lang.Runnable接口。通過重寫run()方法來實現需要執行的業務邏輯;
實例化:通過new一個新的Thread對象來實例化該線程;
執行:調用Thread類的start()方法,啓動新的執行線程(具有新的調用棧)。
其他:線程都可以設置名字,也可以獲取線程的名字,連主線程也不例外。獲取當前線程的對象的方法是:Thread.currentThread();
Java線程:線程狀態的轉換
Java線程:線程的調度
1、睡眠:Thread.sleep(long millis)和Thread.sleep(long millis, int nanos)靜態方法強制當前正在執行的線程休眠(暫停執行)。當線程睡眠時,它入睡在某個地方;當睡眠時間到期,則返回到可運行狀態。
2、讓步:通過Thread.yield()來實現。yield()方法的作用是--讓當前運行線程回到可運行狀態,以允許具有相同優先級的其他線程獲得運行機會。因此,使用yield()的目的是讓相同優先級的線程之間能適當的輪轉執行。
3、阻塞:Thread的非靜態方法join()。例子:t.join()執行時,則當前運行的線程停止執行,直至線程t執行完畢後,再執行後續的剩餘線程。
線程的同步與鎖:
synchronized的使用
使用synchronized來同步需要同步的方法或數據塊。
synchronized可以保證其管轄範圍內的代碼一次全部執行完畢(期間不會造成線程切換)。
synchronized需要獲得相應對象的鎖才能執行其管轄範圍內的代碼:
1、synchronized同步方法時,需要獲得該方法所屬的對象的鎖;
2、synchronized同步靜態方法時,需要獲得該方法所屬的類對象的鎖;
3、synchronized同步數據塊時,需要獲得其()內的對象的鎖。
線程交互的相關方法:
1、Object.wait():導致當前獲得該對象的鎖的線程等待,並釋放出該對象的鎖以供其他線程使用,當前線程等待直到其他線程調用此對象的 notify() 方法或 notifyAll() 方法。
2、Object.notify():喚醒在此對象監視器上等待的單個線程。
3、Object.notifyAll():喚醒在此對象監視器上等待的所有線程。
經典的併發協作案例:
生產消費模型,參見連接 http://lavasoft.blog.51cto.com/62575/221932
線程池:
代碼示例
Executors可以創建多種類型的線程池,示例中創建的是一個固定大小的線程池
通過調用ExecutorService對象的execute(Thread)方法,來將相應的線程提交給線程池,線程池會自動分配資源執行提交給它的所有線程
有返回值的線程Callable
可返回值的任務必須實現Callable接口;類似的無返回值的任務必須Runnable接口。
執行Callable任務後,可以獲取一個Future的對象,在該對象上調用get就可以獲取到Callable任務返回的Object了。
示例如下:
1、調用ExecutorService對象中的submit方法,將Callable實現的線程提交給線程池,線程返回的結果將保存在一個Future對象中;
2、調用Future對象的get()方法來獲取相應線程的執行結果(返回值);
3、Callable對象中的call()方法用來實現有返回值的業務邏輯.