Java多線程理解


首先說一下進程和線程的區別

進程:是計算機運用程序實例,擁有獨立的內存空間和數據(猜測內存堆應該是作用的進程上),一個進程包含多個子線程,不同進程相互獨立;

線程: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

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM