Java并發(fā)編程的藝術(shù)-并發(fā)編程的基礎(chǔ)

線程的狀態(tài)

  • NEW
  • RUNNABLE
  • BLOCKED:線程阻塞于鎖
  • WAITING:等待狀態(tài),當(dāng)前線程需要等待其他線程通知或者中斷才能被喚醒。
  • TIME_WAITING:超時(shí)等待,與waiting狀態(tài)不同的是,它可以在指定的時(shí)間到達(dá)時(shí)返回到運(yùn)行狀態(tài),不一定需要?jiǎng)e的線程的喚醒。
  • TERMINATED

線程狀態(tài)變遷

  • 從RUNNABLE變?yōu)閃AITING狀態(tài)可能的情況
object.wait();//等待object.notify()或者object.notifyAll();
threadA.join();//等待線程threadA執(zhí)行完畢
LockSupport.park();//important,等待相應(yīng)的uppark調(diào)用。
  • 從RUNNABLE到TIME_WAITING類似于上,只是加上了超時(shí)返回。
Thread.sleep(long);
object.wait(long);
threadA.join(long);
LockSupport.park(long);
  • 從RUNNABLE到阻塞狀態(tài)
    等待進(jìn)入synchronized方法和synchronized代碼塊。注意:阻塞在concurrent包中的Lock接口的線程是等待狀態(tài)(因?yàn)榈讓邮褂玫腖ockSupport類中的方法)

線程的創(chuàng)建與銷毀

線程的創(chuàng)建

新建一個(gè)線程對象時(shí):init方法會(huì)從其父線程(當(dāng)前線程)繼承一些信息,比較重要的有(contextClassLoader,daemon,priority,可繼承的ThreadLocal)

線程的啟動(dòng)

thread.start();

中斷

中斷就相當(dāng)與線程與線程之間發(fā)消息一樣,假如threadA中調(diào)用threadB.interrupt(), 那么threadB就會(huì)收到這個(gè)中斷消息并做出響應(yīng)(比如,threadB正在sleep,那么sleep會(huì)馬上結(jié)束并拋出InterruptedException)
對thread.isInterrupted()和Thread.interrupted(檢查當(dāng)前線程中斷表示位)的返回值取決與線程是否還有未被處理的中斷消息。對于上面的例子來說,thread.isInterrupted()返回false,因?yàn)橹袛嘞⒁呀?jīng)被消耗了(返回InterruptedException)

安全的終止線程demo

通過這個(gè)Runner生成的線程對象可以通過中斷關(guān)閉,或者cancel()調(diào)用關(guān)閉

private static class Runner implements Runnable{
        private volatile boolean on = true;
        @Override
        public void run() {
            while (on && !Thread.currentThread().isInterrupted()){
                //do 
            }
        }
          public void cancel() {
                  on = false;
          }
    }

線程間通信

volatile和synchronized關(guān)鍵字的內(nèi)存語義

等待通知機(jī)制

這里主要涉及Object類的幾個(gè)方法

wait();
wait(long);//超時(shí)等待
notify();
notifyAll();

這里以一段生產(chǎn)者消費(fèi)者代碼,這樣寫有點(diǎn)冗余。

  private class Container{
        private int maxCap;
        private int curCap;
        private int toPut;
        private int toGet;
        private int[] data;
        Container(int cap){
            this.maxCap = cap;
            data = new int[cap];
            curCap = toGet = toPut = 0;
        }
        public int get(){
            synchronized (this){
                while (curCap <= 0)
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                int tmp = data[toGet];
                curCap--;
                toGet = toGet + 1 < maxCap ? toGet + 1: 0;
                this.notifyAll();//this can notify the consumer thread also.
                return tmp;
            }
        }
        public void put(int i){
            synchronized (this){
                while (curCap == maxCap){
                    try{
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                data[toPut] = i;
                curCap ++;
                toPut = toPut + 1 < maxCap ? toPut + 1 : 0;
                this.notifyAll();
            }
        }
    }

Thread.join()

如在threadA中調(diào)用threadB.join()那么就會(huì)等threadB返回之后才執(zhí)行A線程中threadB.join()之后的內(nèi)容。
這里其實(shí)是相當(dāng)于 threadB.wait(); 然后線程銷毀時(shí)threadB.notifyAll();

ThreadLocal

ThreadLocal中存儲(chǔ)的鍵值對綁定到線程,當(dāng)其中的值不再使用時(shí)需要置空以便垃圾回收。可以用于方法調(diào)用計(jì)時(shí)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容