首先說一下進程和線程的區別
進程:是計算機運用程序實例,擁有獨立的內存空間和數據(猜測內存堆應該是作用的進程上),一個進程包含多個子線程,不同進程相互獨立;
線程:cpu執行的基本單位,擁有獨立的寄存器和棧,同一進程下的線程共享地址&內存空間;線程棧存放方法的棧幀,每次方法執行都會新建棧幀壓到棧頂,當線程中某個請求大小超過限制則提示StackOverflowError,當需要存儲一個新的棧幀且棧內存不足則拋出OutOfMemoryError;棧幀包含局部變量、返回值、方法引用的常量池(棧幀只能存儲對象的引用)
cpu可以按時間切片執行,單核cpu同一個時刻只支持一個線程執行任務,多線程並發事實上就是多個線程排隊申請調用cpu,cpu處理任務速度非常快,所以看上去多個線程任務說並發處理。
線程各個狀態
1、新建狀態(New):新創建了一個線程對象
2、就緒狀態(Runnable):創建完線程並調用start()方法后等待獲取cpu使用權,獲取線程丟失cpu使用權后等待下一個cpu使用權
3、運行狀態(Running):處於就緒狀態的線程獲取到cpu的使用權,執行程序代碼
4、堵塞狀態(Blocked):當某線程暫時放棄cpu使用權,該線程就處於堵塞狀態,且處於堵塞狀態線程不再申請調度cpu
a、等待堵塞:當對象調用wait方法,當前線程進入等待池,直到等待時間到或者調用該對象的notify方法
b、同步堵塞:當線程訪問帶同步鎖的成員,且此時該同步鎖被其它線程占用,該線程進入鎖池,直到其它線程釋放同步鎖且當前線程獲取到該同步鎖
初
c、其它堵塞:調用當前線程sleep方法或者調用其它線程對象的join方法,直到sleep時間到期或者其它線程任務執行完
5、死亡狀態(Dead):線程任務執行完畢或者線程拋出異常
如上狀態流程圖大體如下
雖然sleep和wait都能使線程進入等待狀態,但兩個方法差別如下:
1、sleep屬於Thread類對象方法,wait屬於Object類對象方法
2、調用線程對象sleep方法使得該線程處於等待狀態,在時間到期之前不會申請調度cpu,如果該線程持有對象鎖,則該線程不會釋放對象鎖;調用對象wait方法,持有該對象的線程進入等待池,且該線程會放棄對象鎖
3、wait,notify等必須結合Synchronized來使用,sleep不需要
寫了一個同步鎖例子,三個子線程依次打印
public static void main(String[] args) { // TODO Auto-generated method stub Thread thread1=new ChildThread("thread1"); Thread thread2=new ChildThread("thread2"); Thread thread3=new ChildThread("thread3"); thread1.start(); thread2.start(); thread3.start(); } public class ChildThread extends Thread{ private static List<ChildThread> dataSource=new ArrayList<>(); private static Object lockObj=new Object(); private static int MaxLength=5; private int currentNumber=1; private String name; public ChildThread(String name) { this.name=name; dataSource.add(this); } @Override public void run() { super.run(); while (currentNumber<=MaxLength) { synchronized (lockObj) { boolean isbellow = isBellow(); if(isbellow){ Log.i(" " ,String.format("%s=%s",name,currentNumber)); currentNumber++; lockObj.notifyAll(); } else{ try { lockObj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } private boolean isBellow(){ boolean isBellow=true; for (ChildThread childThread:dataSource) { if(currentNumber>childThread.currentNumber){ isBellow=false; break; } } return isBellow; } }
結果如下
06-01 23:10:28.153 19108-19148/haozuo.com.myapplication I/: thread3=1
06-01 23:10:28.156 19108-19147/haozuo.com.myapplication I/: thread2=1
06-01 23:10:28.157 19108-19146/haozuo.com.myapplication I/: thread1=1
06-01 23:10:28.157 19108-19146/haozuo.com.myapplication I/: thread1=2
06-01 23:10:28.159 19108-19148/haozuo.com.myapplication I/: thread3=2
06-01 23:10:28.161 19108-19147/haozuo.com.myapplication I/: thread2=2
06-01 23:10:28.161 19108-19147/haozuo.com.myapplication I/: thread2=3
06-01 23:10:28.163 19108-19148/haozuo.com.myapplication I/: thread3=3
06-01 23:10:28.163 19108-19146/haozuo.com.myapplication I/: thread1=3
06-01 23:10:28.163 19108-19146/haozuo.com.myapplication I/: thread1=4
06-01 23:10:28.163 19108-19148/haozuo.com.myapplication I/: thread3=4
06-01 23:10:28.164 19108-19147/haozuo.com.myapplication I/: thread2=4
06-01 23:10:28.164 19108-19147/haozuo.com.myapplication I/: thread2=5
06-01 23:10:28.165 19108-19148/haozuo.com.myapplication I/: thread3=5
06-01 23:10:28.167 19108-19146/haozuo.com.myapplication I/: thread1=5