理論:第八章:線程是什么,有幾種實(shí)現(xiàn)方式,它們之間的區(qū)別是什么,線程池實(shí)現(xiàn)原理,JUC并發(fā)包,ThreadLocal與Lock和Synchronize區(qū)別

什么是線程?講個故事給你聽,讓你沒法去背這個題,地址:https://blog.csdn.net/java_wxid/article/details/94131223

有幾種實(shí)現(xiàn)方式?

    繼承Thread類
    實(shí)現(xiàn)Runnable接口
    實(shí)現(xiàn)Callable接口
    線程池方式

優(yōu)缺點(diǎn)

1.繼承Thread類

    優(yōu)點(diǎn) 、代碼簡單 。
    缺點(diǎn) 、該類無法集成別的類。

2.實(shí)現(xiàn)Runnable接口

    優(yōu)點(diǎn) 、繼承其他類。 同一實(shí)現(xiàn)該接口的實(shí)例可以共享資源。
    缺點(diǎn) 、代碼復(fù)雜

3.實(shí)現(xiàn)Callable

    優(yōu)點(diǎn) 、可以獲得異步任務(wù)的返回值

4.線程池 、實(shí)現(xiàn)自動化裝配,易于管理,循環(huán)利用資源。

代碼實(shí)現(xiàn)案例:

    繼承Thread類,并重寫里面的run方法
    class A extends Thread{
        public void run(){
            for(int i=1;i<=100;i++){
                System.out.println("-----------------"+i);
            }
        }
    }
    A a = new A();
    a.start();
     
    實(shí)現(xiàn)Runnable接口,并實(shí)現(xiàn)里面的run方法
    class B implements Runnable{
        public void run(){
            for(int i=1;i<=100;i++){
                System.out.println("-----------------"+i);
            }
        }
    }
    B b = new B();
    Thread t = new Thread(b);
    t.start();
    實(shí)現(xiàn)Callable
    class A implements Callable<String>{
        public String call() throws Exception{
            //...
        }
    }
    FutureTask<String> ft = new FutureTask<>(new A());
    new Thread(ft).start();
    線程池
    ExcutorService es = Executors.newFixedThreadPool(10);
    es.submit(new Runnable(){//任務(wù)});
    es.submit(new Runnable(){//任務(wù)});
    ...
    es.shutdown();

問題擴(kuò)展

在Java中Lock接口比synchronized塊的優(yōu)勢是什么?你需要實(shí)現(xiàn)一個高效的緩存,它允許多個用戶讀,但只允許一個用戶寫,以此來保持它的完整性,你會怎樣去實(shí)現(xiàn)它?

整體上來說Lock是synchronized的擴(kuò)展版,Lock提供了無條件的、可輪詢的(tryLock方法)、定時的(tryLock帶參方法)、可中斷的(lockInterruptibly)、可多條件隊(duì)列的(newCondition方法)鎖操作。另外Lock的實(shí)現(xiàn)類基本都支持非公平鎖(默認(rèn))和公平鎖,synchronized只支持非公平鎖,當(dāng)然,在大部分情況下,非公平鎖是高效的選擇。

線程池的實(shí)現(xiàn)原理:https://blog.csdn.net/java_wxid/article/details/101844786

JUC并發(fā)包:

    volatile的三大特性:https://blog.csdn.net/java_wxid/article/details/97611028
    CompareAndSwap底層原理:https://blog.csdn.net/java_wxid/article/details/97611037
    AtomicReference原子引用:https://blog.csdn.net/java_wxid/article/details/97611046
    CountDownLatch倒計(jì)時器:https://blog.csdn.net/java_wxid/article/details/99168098
    CyclicBarrier循環(huán)柵欄:https://blog.csdn.net/java_wxid/article/details/99171155
    Semaphore信號燈:https://blog.csdn.net/java_wxid/article/details/99174538

ThreadLocal與Lock和Synchronize區(qū)別

ThreadLocal與Lock和Synchronize區(qū)別
ThreadLocal為每一個線程都提供了變量的副本,使得每個線程在某一時間訪問到的并不是同一個對象,這樣就隔離了多個線程對數(shù)據(jù)的數(shù)據(jù)共享。ThreadLocal采用了“以空間換時間”的方式,為每一個線程都提供了一份變量,因此可以同時訪問而互不影響。
synchronized是利用鎖的機(jī)制,使變量或代碼塊在某一時該只能被一個線程訪問。同步機(jī)制采用了“以時間換空間”的方式,僅提供一份變量,讓不同的線程排隊(duì)訪問。
如果一個代碼塊被synchronized關(guān)鍵字修飾,當(dāng)一個線程獲取了對應(yīng)的鎖,并執(zhí)行該代碼塊時,其他線程便只能一直等待直至占有鎖的線程釋放鎖。事實(shí)上,占有鎖的線程釋放鎖一般會是以下三種情況之一:
占有鎖的線程執(zhí)行完了該代碼塊,然后釋放對鎖的占有;
占有鎖線程執(zhí)行發(fā)生異常,此時JVM會讓線程自動釋放鎖;
占有鎖線程進(jìn)入 WAITING 狀態(tài)從而釋放鎖,例如在該線程中調(diào)用wait()方法等。
synchronized 是Java語言的內(nèi)置特性,可以輕松實(shí)現(xiàn)對臨界資源的同步互斥訪問。那么,為什么還會出現(xiàn)Lock呢?試考慮以下三種情況:
Case 1 :
在使用synchronized關(guān)鍵字的情形下,假如占有鎖的線程由于要等待IO或者其他原因(比如調(diào)用sleep方法)被阻塞了,但是又沒有釋放鎖,那么其他線程就只能一直等待,別無他法。這會極大影響程序執(zhí)行效率。因此,就需要有一種機(jī)制可以不讓等待的線程一直無期限地等待下去(比如只等待一定的時間 (解決方案:tryLock(long time, TimeUnit unit)) 或者 能夠響應(yīng)中斷 (解決方案:lockInterruptibly())),這種情況可以通過 Lock 解決。
Case 2 :
我們知道,當(dāng)多個線程讀寫文件時,讀操作和寫操作會發(fā)生沖突現(xiàn)象,寫操作和寫操作也會發(fā)生沖突現(xiàn)象,但是讀操作和讀操作不會發(fā)生沖突現(xiàn)象。但是如果采用synchronized關(guān)鍵字實(shí)現(xiàn)同步的話,就會導(dǎo)致一個問題,即當(dāng)多個線程都只是進(jìn)行讀操作時,也只有一個線程在可以進(jìn)行讀操作,其他線程只能等待鎖的釋放而無法進(jìn)行讀操作。因此,需要一種機(jī)制來使得當(dāng)多個線程都只是進(jìn)行讀操作時,線程之間不會發(fā)生沖突。同樣地,Lock也可以解決這種情況 (解決方案:ReentrantReadWriteLock) 。
Case 3 :
我們可以通過Lock得知線程有沒有成功獲取到鎖 (解決方案:ReentrantLock) ,但這個是synchronized無法辦到的。
上面提到的三種情形,我們都可以通過Lock來解決,但 synchronized 關(guān)鍵字卻無能為力。事實(shí)上,Lock 是 java.util.concurrent.locks包 下的接口,Lock 實(shí)現(xiàn)提供了比 synchronized 關(guān)鍵字 更廣泛的鎖操作,它能以更優(yōu)雅的方式處理線程同步問題。也就是說,Lock提供了比synchronized更多的功能。但是要注意以下幾點(diǎn):
1)synchronized是Java的關(guān)鍵字,因此是Java的內(nèi)置特性,是基于JVM層面實(shí)現(xiàn)的。而Lock是一個Java接口,是基于JDK層面實(shí)現(xiàn)的,通過這個接口可以實(shí)現(xiàn)同步訪問;
2)采用synchronized方式不需要用戶去手動釋放鎖,當(dāng)synchronized方法或者synchronized代碼塊執(zhí)行完之后,系統(tǒng)會自動讓線程釋放對鎖的占用;而 Lock則必須要用戶去手動釋放鎖,如果沒有主動釋放鎖,就有可能導(dǎo)致死鎖現(xiàn)象。

關(guān)于讀寫鎖:https://blog.csdn.net/java_wxid/article/details/99165717