通常,用并發(fā)結(jié)局的問題大體上可以分為“速度”和“設(shè)計(jì)可管理性”兩種。
頻繁的線程間切換,有效的避免“阻塞”問題;仿真相關(guān)的問題。java中通常有兩種方式創(chuàng)建線程:
擴(kuò)展java.lang.Thread類
public class taskT extends Thread{ public void run() { System.out.實(shí)現(xiàn)java.lang.Runnable接口
public class taskR implements Runnable{ @Override public void run() { System.out.println("正在執(zhí)行Runnable!"); } } public static void main(String[] args) { taskR r = new taskR(); Thread thread = new Thread(r); thread.start(); }一旦創(chuàng)建一個(gè)新線程并開始執(zhí)行,即調(diào)用start方法時(shí),虛擬機(jī)中就又多一個(gè)進(jìn)程,這個(gè)進(jìn)程和原先的進(jìn)程時(shí)并行的。
public class TaskR implements Runnable{ @Override public void run() { System.out.println("正在執(zhí)行線程B!"); System.out.println("已經(jīng)執(zhí)行完線程B!"); }}public class test { public static void main(String[] args) { System.out.println("正在執(zhí)行main函數(shù)111!"); TaskR b = new TaskR(); Thread threadB = new Thread(b); System.out.println("準(zhǔn)備添加線程B!"); threadB.start(); System.out.println("繼續(xù)執(zhí)行main函數(shù)222!");// for (int i = 0; i < 999999; i++);//延時(shí)代碼 System.out.println("正在執(zhí)行main函數(shù)333!"); }}如上程序執(zhí)行結(jié)果輸出如下:
正在執(zhí)行main函數(shù)111!準(zhǔn)備添加線程B!繼續(xù)執(zhí)行main函數(shù)222!正在執(zhí)行main函數(shù)333!正在執(zhí)行線程B!已經(jīng)執(zhí)行完線程B!將main函數(shù)的注釋代碼去除注釋,增加代碼延時(shí),輸出如下:
正在執(zhí)行main函數(shù)111!準(zhǔn)備添加線程B!繼續(xù)執(zhí)行main函數(shù)222!正在執(zhí)行線程B!已經(jīng)執(zhí)行完線程B!正在執(zhí)行main函數(shù)333!由上兩組對比不難發(fā)現(xiàn),當(dāng)線程threadB一旦開始執(zhí)行(執(zhí)行threadbB.start()),main函數(shù)這條線程和線程threadB是并發(fā)的。
另外需要注意的是,多線程表面上給人的感覺是多個(gè)任務(wù)同時(shí)進(jìn)行,實(shí)際上并非如此,虛擬機(jī)通過頻繁的切換進(jìn)程來給人同時(shí)執(zhí)行的錯(cuò)覺。
2.線程狀態(tài)的轉(zhuǎn)換線程的狀態(tài)是線程控制的基礎(chǔ)。線程狀態(tài)總的可以分為五大類:生、等待、阻塞、睡眠、死。
當(dāng)多個(gè)線程同時(shí)訪問互斥(可交換)數(shù)據(jù)時(shí),應(yīng)該同步以保護(hù)數(shù)據(jù),確保兩個(gè)線程不會同時(shí)更改它。通常用synchronized字段實(shí)現(xiàn),而且只能同步方法或同步代碼快。
如果兩個(gè)線程要執(zhí)行一個(gè)類中的synchronized方法,并且兩個(gè)線程使用相同的實(shí)例來調(diào)用方法,那么一次只能有一個(gè)線程能夠執(zhí)行方法,另一個(gè)需要等待,直到鎖被釋放。
4.線程的交換合并:join():join()方法是是在某個(gè)線程a中,加入一個(gè)線程b,線程b沒執(zhí)行完前,a不得執(zhí)行。
public class TaskR implements Runnable{ @Override public void run() { System.out.println("正在執(zhí)行線程B!"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("已經(jīng)執(zhí)行完線程B!"); } } public class test { public static void main(String[] args) throws InterruptedException { System.out.println("正在執(zhí)行main函數(shù)!"); TaskR b = new TaskR(); Thread threadB = new Thread(b); System.out.println("準(zhǔn)備添加線程B!"); threadB.start(); System.out.println("執(zhí)行完main"); } } public class test2 { public static void main(String[] args) throws InterruptedException { System.out.println("正在執(zhí)行main函數(shù)!"); TaskR b = new TaskR(); Thread threadB = new Thread(b); System.out.println("準(zhǔn)備添加線程B!"); threadB.start(); System.out.println("threadB.join()"); threadB.join(); System.out.println("執(zhí)行完main"); } }分別執(zhí)行test1和test2中的main執(zhí)行結(jié)果如下:
正在執(zhí)行main函數(shù)! 準(zhǔn)備添加線程B! threadB.join() 執(zhí)行完main 正在執(zhí)行線程B! 已經(jīng)執(zhí)行完線程B!test2中添加join()方法:
正在執(zhí)行main函數(shù)! 準(zhǔn)備添加線程B! threadB.join() 正在執(zhí)行線程B! 已經(jīng)執(zhí)行完線程B! 執(zhí)行完main在threadB中調(diào)用sleep是為了讓main函數(shù)這條線程獲得執(zhí)行機(jī)會。有結(jié)果,可知當(dāng)threadB調(diào)用join方法后,即使sleep了main函數(shù)都不能跑完,說明join方法的作用,即必須threadB執(zhí)行完才能繼續(xù)執(zhí)行main函數(shù)。
java.util.concurrent.Executors。 例:
ExecutorService pool = Executors.newFixedThreadPool(2);Thread t1 = new MyThread(); Thread t2 = new MyThread();Thread t3 = new MyThread();Thread t4 = new MyThread();pool.execute(t1);pool.execute(t2);pool.execute(t3);pool.execute(t4);pool.shutdown();新聞熱點(diǎn)
疑難解答
圖片精選