成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java的一些題目

jokester / 3179人閱讀

摘要:需要注意的是對(duì)于方法或者代碼塊,當(dāng)出現(xiàn)異常時(shí),會(huì)自動(dòng)釋放當(dāng)前線程占用的鎖,因此不會(huì)由于異常導(dǎo)致出現(xiàn)死鎖現(xiàn)象。用于實(shí)現(xiàn)線程間的通信,它是為了解決難以使用的問題。

速度StringBuilder>StringBuffer>String,StringBuffer線程安全

線程安全的集合有:Vector、Stack、HashTable、ConcurrentHashMap、

CopyOnWriteXXX(如CopyOnWriteArrayList)

ClassLoader

程序在啟動(dòng)的時(shí)候,并不會(huì)一次性加載程序所要用的所有class文件,而是根據(jù)程序的需要,通過(guò)Java的類加載機(jī)制(ClassLoader)來(lái)動(dòng)態(tài)加載某個(gè)class文件到內(nèi)存當(dāng)中的,從而只有class文件被載入到了內(nèi)存之后,才能被其它c(diǎn)lass所引用。所以ClassLoader就是用來(lái)動(dòng)態(tài)加載class文件到內(nèi)存當(dāng)中用的。

Java默認(rèn)提供的三個(gè)ClassLoader。BootStrap ClassLoader:稱為啟動(dòng)類加載器,是Java類加載層次中最頂層的類加載器,負(fù)責(zé)加載JDK中的核心類庫(kù),如:rt.jar、resources.jar、charsets.jar等。

Extension ClassLoader:稱為擴(kuò)展類加載器,負(fù)責(zé)加載Java的擴(kuò)展類庫(kù),默認(rèn)加載JAVA_HOME/jre/lib/ext/目下的所有jar。

App ClassLoader:稱為系統(tǒng)類加載器,負(fù)責(zé)加載應(yīng)用程序classpath目錄下的所有jar和class文件。

ClassLoader使用的是雙親委托模型來(lái)搜索類的,每個(gè)ClassLoader實(shí)例都有一個(gè)父類加載器的引用(不是繼承的關(guān)系,是一個(gè)包含的關(guān)系),虛擬機(jī)內(nèi)置的類加載器(Bootstrap ClassLoader)本身沒有父類加載器,但可以用作其它ClassLoader實(shí)例的的父類加載器。

JVM在判定兩個(gè)class是否相同時(shí),不僅要判斷兩個(gè)類名是否相同,而且要判斷是否由同一個(gè)類加載器實(shí)例加載的。只有兩者同時(shí)滿足的情況下,JVM才認(rèn)為這兩個(gè)class是相同的
Java ClassLoader原理

synchronized lock

淺談Java并發(fā)編程系列(五)Java并發(fā)編程之線程同步

當(dāng)一個(gè)線程正在訪問一個(gè)對(duì)象的synchronized方法,那么其他線程不能訪問該對(duì)象的其他synchronized方法,因?yàn)橐粋€(gè)對(duì)象只有一把鎖,當(dāng)一個(gè)線程獲取了該對(duì)象的鎖之后,其他線程無(wú)法獲取該對(duì)象的鎖,所有無(wú)法訪問該對(duì)象的其他synchronized方法。
當(dāng)一個(gè)線程正在訪問一個(gè)對(duì)象的synchronized方法,那么其他線程能訪問該對(duì)象的非synchronized方法。因?yàn)榉莝ynchronized方法不需要獲取該對(duì)象的鎖。
如果一個(gè)線程A需要訪問對(duì)象object1的synchronized方法fun1,另外一個(gè)線程B需要訪問對(duì)象object2的synchronized方法fun1,即使object1和object2是同一類型,也不會(huì)產(chǎn)生線程安全問題,因?yàn)樗麄冊(cè)L問的是不同的對(duì)象,所以不存在互斥問題。
如果一個(gè)線程執(zhí)行一個(gè)對(duì)象的非static synchronized方法,另一個(gè)線程執(zhí)行這個(gè)對(duì)象所屬類的static synchronized方法,此時(shí)不會(huì)發(fā)生互斥現(xiàn)象,因?yàn)樵L問static synchronized方法占用的是類鎖,而訪問非static synchronized方法占用的是對(duì)象鎖,所以不存在互斥現(xiàn)象。
需要注意的是:對(duì)于synchronized方法或者synchronized代碼塊,當(dāng)出現(xiàn)異常時(shí),JVM會(huì)自動(dòng)釋放當(dāng)前線程占用的鎖,因此不會(huì)由于異常導(dǎo)致出現(xiàn)死鎖現(xiàn)象。
顯式鎖ReentrantLock則可以將鎖的獲得和釋放分開。同時(shí)顯式鎖可以提供輪訓(xùn)鎖和定時(shí)鎖,同時(shí)可以提供公平鎖或者非公平鎖。

ReentrantLock和Condition的關(guān)系

在ReentrantLock類中有一個(gè)重要的函數(shù)newCondition(),該函數(shù)用于獲取lock上的一個(gè)條件,也就是說(shuō)Condition是和Lock綁定的。Condition用于實(shí)現(xiàn)線程間的通信,它是為了解決Object.wait()、notify()、notifyAll()難以使用的問題。
public class MyArrayBlockingQueue {

    // 數(shù)據(jù)數(shù)組
    private final T[] items;
    // 鎖
    private final Lock mLock = new ReentrantLock();
    // 數(shù)組滿的條件
    private Condition notFull = mLock.newCondition();
    // 數(shù)組空的條件
    private Condition notEmpty = mLock.newCondition();

    // 頭部
    private int head;
    // 尾部
    private int tail;
    // 數(shù)據(jù)數(shù)量
    private int count;

    public MyArrayBlockingQueue(int maxSize) {
        // TODO Auto-generated constructor stub
        items = (T[]) new Object[maxSize];
    }

    public MyArrayBlockingQueue() {
        // TODO Auto-generated constructor stub
        this(10);
    }

    public void put(T t) {

        mLock.lock();

        try {

            // 如果數(shù)據(jù)已滿,等待
            while (count == getCapacity()) {
                System.out.println("數(shù)據(jù)已滿,請(qǐng)等待");
                notFull.await();
            }

            System.out.println("存入數(shù)據(jù)");

            items[tail] = t;
            if (++tail == getCapacity()) {
                tail = 0;
            }

            ++count;
            // 喚醒等待數(shù)據(jù)的線程
            notEmpty.signalAll();

        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            mLock.unlock();
        }
    }

    public T take() {

        mLock.lock();

        try {

            // 如果數(shù)組數(shù)據(jù)為空,則阻塞
            while (count == 0) {
                System.out.println("還沒有數(shù)據(jù),等待");
                notEmpty.await();
            }

            System.out.println("取出數(shù)據(jù)");

            T t = items[head];
            items[head] = null;

            if (++head == getCapacity()) {
                head = 0;
            }

            --count;
            // 喚醒添加數(shù)據(jù)的線程
            notFull.signalAll();
            return t;

        } catch (InterruptedException e) {
            // TODO: handle exception
        } finally {
            mLock.unlock();
        }

        return null;
    }

    public int getCapacity() {
        return items.length;
    }

    public int size() {
        mLock.lock();
        try {
            return count;
        } finally {
            mLock.unlock();
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        final MyArrayBlockingQueue mQueue = new MyArrayBlockingQueue<>(
                5);

        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (true) {

                    for(int i  = 0;i < 3;i++)
                    mQueue.put("just");
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }

            }
        }).start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (true) {
                    
                    mQueue.take();

                }
            }
        }).start();

    }

}

結(jié)果打印
存入數(shù)據(jù)
存入數(shù)據(jù)
存入數(shù)據(jù)
取出數(shù)據(jù)
取出數(shù)據(jù)
取出數(shù)據(jù)
還沒有數(shù)據(jù),等待
存入數(shù)據(jù)
存入數(shù)據(jù)
存入數(shù)據(jù)
取出數(shù)據(jù)
取出數(shù)據(jù)
取出數(shù)據(jù)
還沒有數(shù)據(jù),等待
當(dāng)時(shí)看到這段代碼我就想到一個(gè)問題:如果一個(gè)線程lock()對(duì)象后被掛起還沒有unlock,那么另外一個(gè)線程就拿不到鎖了(lock()操作會(huì)掛起),那么就無(wú)法通知(notify)前一個(gè)線程,這樣豈不是“死鎖”了?

再回頭看代碼,不管take()還是put(),在進(jìn)入lock.lock()后唯一可能釋放鎖的操作就是await()了。也就是說(shuō)await()操作實(shí)際上就是釋放鎖,然后掛起線程,一旦條件滿足就被喚醒,再次獲取鎖!

await源碼如下

public final void await() throws InterruptedException {  
    if (Thread.interrupted())  
        throw new InterruptedException();  
    Node node = addConditionWaiter();  
    int savedState = fullyRelease(node);  
    int interruptMode = 0;  
    while (!isOnSyncQueue(node)) {  
        LockSupport.park(this);  
        if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)  
            break;  
    }  
    if (acquireQueued(node, savedState) && interruptMode != THROW_IE)  
        interruptMode = REINTERRUPT;  
    if (node.nextWaiter != null)  
        unlinkCancelledWaiters();  
    if (interruptMode != 0)  
        reportInterruptAfterWait(interruptMode);  
}  

完整的await()操作是安裝如下步驟進(jìn)行的:

將當(dāng)前線程加入Condition鎖隊(duì)列。特別說(shuō)明的是,這里不同于AQS的隊(duì)列,這里進(jìn)入的是Condition的FIFO隊(duì)列。后面會(huì)具體談到此結(jié)構(gòu)。進(jìn)行2。

釋放鎖。這里可以看到將鎖釋放了,否則別的線程就無(wú)法拿到鎖而發(fā)生死鎖。進(jìn)行3。

自旋(while)掛起,直到被喚醒或者超時(shí)或者CACELLED等。進(jìn)行4。

獲取鎖(acquireQueued)。并將自己從Condition的FIFO隊(duì)列中釋放,表明自己不再需要鎖(我已經(jīng)拿到鎖了)。

介紹Condition的數(shù)據(jù)結(jié)構(gòu)。我們知道一個(gè)Condition可以在多個(gè)地方被await*(),那么就需要一個(gè)FIFO的結(jié)構(gòu)將這些Condition串聯(lián)起來(lái),然后根據(jù)需要喚醒一個(gè)或者多個(gè)(通常是所有)。所以在Condition內(nèi)部就需要一個(gè)FIFO的隊(duì)列。

//conditon 的兩個(gè)屬性
private transient Node firstWaiter;  
private transient Node lastWaiter; 
這兩個(gè)節(jié)點(diǎn)就是描述一個(gè)FIFO的隊(duì)列。我們?cè)俳Y(jié)合前面提到的節(jié)點(diǎn)(Node)數(shù)據(jù)結(jié)構(gòu)。我們就發(fā)現(xiàn)Node.nextWaiter就派上用場(chǎng)了!nextWaiter就是將一系列的Condition.await*串聯(lián)起來(lái)組成一個(gè)FIFO的隊(duì)列。

wait和sleep的區(qū)別

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/70373.html

相關(guān)文章

  • java之thread.yield

    摘要:,看到很多文章把理解為暫停,其實(shí)是不準(zhǔn)確的,翻譯過(guò)來(lái)用讓步更為準(zhǔn)確一些。如下在中我們可以看到官方的解釋,更多的是作為調(diào)試或測(cè)試時(shí)候使用也就是瘋狂重分配,提高切換概率,模擬并發(fā) yield,看到很多文章把yield理解為暫停,其實(shí)是不準(zhǔn)確的,翻譯過(guò)來(lái)用讓步更為準(zhǔn)確一些。簡(jiǎn)單描述下其作用: 使調(diào)用yield的正在執(zhí)行的線程讓出cpu,讓同等優(yōu)先權(quán)的其他線程包括自身重新進(jìn)行分配調(diào)度 概念性的...

    YPHP 評(píng)論0 收藏0
  • 關(guān)于 Java強(qiáng)制類型轉(zhuǎn)換

    摘要:?jiǎn)栴}描述遇到一個(gè)題目經(jīng)過(guò)強(qiáng)制類型轉(zhuǎn)換以后,變量,的值分別為多少答案是這涉及到的,打算借此稍稍研究一下。分為兩種,一是擴(kuò)展型基本數(shù)據(jù)類型轉(zhuǎn)換,二是窄化型基本數(shù)據(jù)類型轉(zhuǎn)換。需要注意的是是有可能丟失數(shù)值的整體信息以及損失精度和范圍的。 問題描述 遇到一個(gè)題目: 經(jīng)過(guò)強(qiáng)制類型轉(zhuǎn)換以后,變量a,b的值分別為多少? short a = 128; byte b = (byte) a;a = ?,...

    wind5o 評(píng)論0 收藏0
  • 從簡(jiǎn)歷被拒到收割今日頭條 offer,我用一年時(shí)間破繭成蝶!

    摘要:正如我標(biāo)題所說(shuō),簡(jiǎn)歷被拒??戳宋液?jiǎn)歷之后說(shuō)頭條競(jìng)爭(zhēng)激烈,我背景不夠,點(diǎn)到為止。。三準(zhǔn)備面試其實(shí)從三月份投遞簡(jiǎn)歷開始準(zhǔn)備面試到四月份收,也不過(guò)個(gè)月的時(shí)間,但這都是建立在我過(guò)去一年的積累啊。 本文是 無(wú)精瘋 同學(xué)投稿的面試經(jīng)歷 關(guān)注微信公眾號(hào):進(jìn)擊的java程序員K,即可獲取最新BAT面試資料一份 在此感謝 無(wú)精瘋 同學(xué)的分享 目錄: 印象中的頭條 面試背景 準(zhǔn)備面試 ...

    tracymac7 評(píng)論0 收藏0
  • 從簡(jiǎn)歷被拒到收割今日頭條 offer,我用一年時(shí)間破繭成蝶!

    摘要:正如我標(biāo)題所說(shuō),簡(jiǎn)歷被拒??戳宋液?jiǎn)歷之后說(shuō)頭條競(jìng)爭(zhēng)激烈,我背景不夠,點(diǎn)到為止。。三準(zhǔn)備面試其實(shí)從三月份投遞簡(jiǎn)歷開始準(zhǔn)備面試到四月份收,也不過(guò)個(gè)月的時(shí)間,但這都是建立在我過(guò)去一年的積累啊。 本文是 無(wú)精瘋 同學(xué)投稿的面試經(jīng)歷 關(guān)注微信公眾號(hào):進(jìn)擊的java程序員K,即可獲取最新BAT面試資料一份 在此感謝 無(wú)精瘋 同學(xué)的分享目錄:印象中的頭條面試背景準(zhǔn)備面試頭條一面(Java+項(xiàng)目)頭條...

    wdzgege 評(píng)論0 收藏0
  • 《十萬(wàn)字Java入門練習(xí)100例》1-10例——紙上得來(lái)終覺淺,絕知此事要躬行

    摘要:代碼實(shí)現(xiàn)在控制臺(tái)打印總結(jié)本篇文章帶大家搭好環(huán)境,并體驗(yàn)了控制臺(tái)打印。輸出結(jié)果總結(jié)熟練掌握取余和整除運(yùn)算,大有作用。終止本次循環(huán),繼續(xù)執(zhí)行下一次循環(huán)。 ?本文收錄...

    keithyau 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

jokester

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<