天天看點

多線程基礎

線程是一個程式内部的順序控制流。

線程和程序的差別:

  每個程序都有獨立的代碼和資料空間(程序上下文),程序間的切換會有較大的開銷。

  線程可以看成是輕量級的程序,同一類線程共享代碼和資料空間,每個線程有獨立的運作棧和程式計數器(pc),線程切換的開銷小。

  多程序:在作業系統中能同時運作多個任務(程式)

  多線程:在同一應用程式中有多個順序流同時執行

當多線程sleep時,如何停止呢?

1、interrupt()方法,這個方法很粗暴不建議使用,這個相當于睡覺的時候一盆涼水潑下來,會抛出interruptedexception。

2、stop()方法,已經廢棄了,這個比interrupt更粗暴,直接停止線程。不建議使用。

3、用标量在外部控制。

join方法:合并某個線程。把處于并行運作狀态的線程合并到目前線程中。

yield()方法:讓出cpu,給其他線程執行的機會。

setpriority():設定優先級,優先級越高,cpu分得時間片就越多,越容易得到執行。

線程同步:在java語言中,引入了對象互斥鎖的概念,保證共享資料操作的完整性。每個對象都對應于一個可稱為“互斥鎖”的标記。這個标記保證在任何一個時刻,隻能有一個線程通路該對象。

關鍵字synchronized來與對象的互斥鎖聯系。當某個對象synchronized修飾時,表明該對象在任一時刻隻能由一個線程通路。synchronized可以作為關鍵字設在方法上,也可以使用synchronized(this){}中表明鎖定該對象的内容。

盡量隻鎖定一個對象,避免死鎖。

當一個線程鎖定了一個方法的時候,其他線程可以通過其他方法修改值,是以,一定要保證所有有關這個變量的方法都要加鎖。

同步執行個體:

多線程基礎

<span style="font-family:microsoft yahei;"><span style="font-size:12px;">package thread;  

public class tt implements runnable{  

    int b = 100 ;  

    @override  

    public void run() {  

        m1() ;  

    }  

    //隻會鎖定m1方法内的内容,不會鎖定b  

    public synchronized void m1() {  

        b = 1000 ;  

        try {  

            thread.sleep(5000);  

        } catch (interruptedexception e) {  

            e.printstacktrace();  

        }  

        system.out.println("b = " + b);  

    public void m2() {  

        system.out.println(b);  

    public static void main(string[] args) {  

        tt t = new tt() ;  

        thread thread = new thread(t) ;  

        thread.start() ;  

            thread.sleep(1000);  

        t.m2();  

}  

</span></span>  

生産者與消費者執行個體:

多線程基礎

<span style="font-family:microsoft yahei;">package thread;  

public class producerconsumer {  

        syncstack ss = new syncstack() ;  

        producer p = new producer(ss) ;  

        consumer c = new consumer(ss) ;  

        new thread(p).start();  

        new thread(c).start();  

class wotou {  

    int id ;  

    wotou(int id) {  

        this.id = id ;  

    public string tostring() {  

        return "id = " + this.id ;  

class syncstack {  

    int index = 0 ;  

    wotou[] arrwt = new wotou[6] ;  

    public synchronized void push(wotou wt) {  

        while(index == arrwt.length) {  

            try {  

                this.wait();  

            } catch (interruptedexception e) {  

                // todo auto-generated catch block  

                e.printstacktrace();  

            }  

        this.notify();  

        arrwt[index] = wt ;  

        index ++ ;  

    public synchronized wotou pop() {  

        while(index == 0) {  

        index -- ;  

        return arrwt[index] ;  

class producer implements runnable {  

    syncstack s = null ;  

    public producer(syncstack s) {  

        this.s = s ;  

        for(int i=0; i<20; i++) {  

            wotou wt = new wotou(i) ;  

            system.out.println("push : " + wt);  

            s.push(wt);  

class consumer implements runnable {  

    public consumer(syncstack s) {  

            wotou wt = s.pop() ;  

            system.out.println("pop : " + wt);  

}</span>  

wait和sleep的差別

wait時别的線程可以通路鎖定對象,調用wait方法的時候必須鎖定該對象。sleep時别的線程也不可以通路鎖定對象。