多線程(二)
阿新 • • 發佈:2017-10-25
程序 mit 方法調用 種類 不同的 get 所有 啟動 highlight
1、JDK5以後的針對線程的鎖定操作和釋放操作
A:為了更清晰表達在哪裏如何加鎖及釋放鎖 B:Lock鎖 lock():加鎖 unlock():釋放鎖 C:ReentrantLock 是 Lock 的實現類 private Lock lock = new ReentrantLock(); lock.lock(); //加鎖 ... //加鎖代碼 lock.unlock(); //釋放鎖
2、死鎖問題的描述和代碼體現
指兩個或兩個以上的線程在執行過程中,因爭奪資源產生的一種互相等待現象(如果出現了同步嵌套,就容易 產生死鎖問題)
3、生產者和消費者多線程體現(線程間通信問題)
A:不同種類的線程間針對同一個資源的操作 代碼實現: //在外界把這個數據創建出來,通過構造方法傳遞給其它類 Student s = new Student(); GetThread gt = new GetThread(s); SetThread st = new SetThread(s); B:以學生作為資源來實現的 資源類:Student 設置數據類:SetThread(生產者) 獲取數據類:GetThread(消費者) 測試類:StudentDemo 代碼: A:最基本的版本,只有一個數據。 B:改進版本,給出了不同的數據,並加入了同步機制 C:等待喚醒機制改進該程序,讓數據能夠實現依次的出現 wait() notify() notifyAll() (多生產多消費) D:等待喚醒機制的代碼優化。把數據及操作都寫在了資源類中 註:這些方法調用必須通過鎖對象調用,而我們剛才使用的鎖對象是任意鎖對象。 所以,這些方法必須定義在Object類中。
4、線程組
把多個線程組合到一起。它可以對一批線程進行分類管理,Java允許程序直接對線程組進行控制。 public final ThreadGroup getThreadGroup():返回該線程所屬的線程組 ThreadGroup tg = mt.getThreadGroup(); public final String getName():返回此線程組的名稱 String name1 = tg.getName(); 註:默認情況下,所有線程都屬於同一個組 ThreadGroup(String name):修改線程所在的組 MyRunnable my = new MyRunnable(); ThreadGroup tg2 = new ThreadGroup("newThreadGroup"); Thread t = new Thread(tg2, my, "threadName"); tg2.get...
5、線程池
程序啟動一個新線程成本比較高,使用線程池可以很好的提高性能,尤其是創建大量生存期很短的線程時, 更應該考慮使用線程池。 線程池裏的每一個線程代碼結束後,並不會死亡,而是再次回到線程池中成為空閑狀態,等待下一個對象 來使用。 在JDK5之前,我們必須手動實現自己的線程池,從JDK5開始,Java內置支持線程池。 線程池的實現: A: 創建一個線程池對象,控制要創建幾個線程對象 public static ExecutorService newFixedThreadPool(int nThreads) B: 這種線程池可以執行 可以執行Runnable對象或者Callable對象代表的線程 做一個類實現Runnable接口 C: 調用如下方法即可 Future<?> submit(Runnable task) Future submit(Callable task) D: 非要結束 pool.shutdown(); 代碼案例: public static void main(String[] args){ //創建一個線程池對象,控制要創建幾個線程對象 ExecutorService pool = new ExecutorService.newFixedThreadPool(2); //可以執行Runnable對象或者Callable對象代表的線程 pool.submit(new MyRunnable()); pool.submit(new MyRunnable()); //結束線程池 pool.shutdown(); }
6、多線程實現的第三種方案
實現Callable接口,與Runnable類似 代碼案例--10
7、匿名內部類方式實現多線程
A:new Thread(){代碼...}.start(); B:new Thread(new Runnable(){代碼...}){}.start(); 代碼案例: //繼承Thread類來實現多線程 new Thread(){ public void run(){ ... } }.start(); //實現Runnable接口來實現多線程 new Thread(new Runnable(){ public void run(){ ... } }){}.start();
8、定時器
可在指定時間執行某任務,還可以重復執行 依賴Timer 和TimerTask Timer:定時 public Timer() public void schedule(TimerTask task, long delay) public void schedule(TimerTask task) public void cancel(); 代碼案例: public static void main(String[] args){ //創建定時器對象 Timer t = new Timer(); //3秒後執行爆炸任務 //t.schedule(new MyTask(), 3000); //結束任務 t.schedule(new MyTask(t), 3000); } class MyTask extends TimerTask(){ private Timer t; public MyTask(){} public MyTask(Timer t){ this.t = t; } public void run(){ System.out.println("beng!!!"); t.cancel(); } }
9、多線程的面試題
A:多線程有幾種實現方案,分別是哪幾種? 繼承Thred類 實現Runnable接口 擴展:實現Callable接口,需要和線程池結合 B:同步有幾種方式,分別是什麽? 兩種 同步代碼塊 同步方法 C:啟動一個線程是run()還是start()?他們的區別是? start(); run():封裝了被線程執行的代碼,直接調用僅僅是普通方法調用 start():啟動線程,並由JVM自動調用run()方法 D:sleep()和wait()方法的區別 sleep():必須指定時間。不釋放鎖 wait():可以不指定時間,也可以指定時間,釋放鎖。 E:為什麽wait(),notify(),notifyAll()等方法定義在Object類中 因為這些方法的調用是依賴鎖對象的,而同步代碼塊的鎖對象是任意鎖。 F:線程的生命周期 新建--就緒--運行--死亡 新建--就緒--運行--阻塞--就緒--運行--死亡 建議畫圖解釋
多線程(二)