Java基礎知識、hashmap、AQS、ThredPoolExecutor

1,StringBuild、StringBuffer、String 區別,Integer a= 130 與 Integer Integer b= 130 相等麼,120呢?爲什麼
(-128,127做了緩存,所以是同一個對象,主要是基於效率考慮,防止頻繁創建)
2,瞭解java的集合有哪些

ArrayList,Vector,LinkedList,HashSet(底層HashMap),LinkedHashSet,TreeSet,HashMap,TreeMap

https://blog.csdn.net/lovewebeye/article/details/79573530

3,瞭解hashmap的實現麼?它是如何解決衝突的?爲什麼擴容是2n次方,爲什麼不用平衡二叉樹

(或者問jdk7 與jdk8有哪些區別,做了哪些優化)

a,底層是是數組+鏈表的結構,jdk8 引入紅黑樹,鏈表節點>8個,就轉化爲紅黑樹

b,開發地址法(線性探測、平方探測)、鏈地址法、再哈希、建立公共溢出區

c,爲2的冪-1都是11111結尾的,所以碰撞機率小。如 index =(h & length - 1),而且 &比 %運算效率高

數組的特點:查詢效率高,插入,刪除效率低。鏈表的特點:查詢效率低,插入刪除效率高。

在HashMap底層使用數組加(鏈表或紅黑樹)的結構完美的解決了數組和鏈表的問題,使得查詢和插入,刪除的效率都很高。

紅黑樹:不追求"完全平衡",增刪都能在三次旋轉達到平衡,比平衡二叉樹效率高,讀取略遜於AVL(查詢性能只比相同內容的AVL樹最多多一次比較),維護強於AVL,空間開銷與AVL類似,內容極多時略優於AVL,維護優於AVL。

4,線程安全的hashMap是哪個?

ConcurrentHashMap,jdk7利用分段鎖技術+volatile技術,put加鎖,get不需要,比hashtable效率高

jdk8採用CAS+synchronized,放棄分段鎖

  1. 加入多個分段鎖浪費內存空間。
  2. 生產環境中, map 在放入時競爭同一個鎖的概率非常小,分段鎖反而會造成更新等操作的長時間等待。
  3. 爲了提高 GC 的效率

5,volatile ,解決:變量的內存可見性,基於內存屏障(Memory Barrier)實現。

volatile應用場景:狀態標誌一次性安全發佈,溫度計,安全計數(++i),雙重檢查(單例模式)

Atomic包裏的主要利用volatile + UnSafe.compareAndSet()保證原子性和可見性

6,java中的鎖、內存模型、內存區域劃分、類加載過程

https://blog.csdn.net/lovewebeye/article/details/105478801

7,垃圾回收機制

 

7,JUC源碼看過麼?如:AQS有哪些?

AQS是一個同步框架,通過維護一個int類型的變量state和一個先進先出隊列,實現共享資源的訪問控制和線程阻塞,其提供了一些基類實現排隊和阻塞機制.

  1. FairSync/NonfairSync (ReentantLock中的、ReentrantReadWriteLock中的)
  2. Semaphore
  3. CountDownLatch 
  4. Worker(ThredPoolExecutor類中) 

1)CountDownLatch和CyclicBarrier都能夠實現線程之間的等待,只不過它們側重點不同:

  CountDownLatch等待多個線程完成,不阻塞任務線程;

  而CyclicBarrier等待多個線程一起開始,阻塞任務線程;

  另外,CountDownLatch是不能夠重用的,而CyclicBarrier是可以重用的。

2)Semaphore其實和鎖有點類似,它一般用於控制對某組資源的訪問權限。

3)如果當前線程不是鎖的佔有者,則NonfairSync並不判斷是否有等待隊列,直接使用compareAndSwap去進行鎖的佔用;

如果當前線程不是鎖的佔有者,則FairSync則會判斷當前是否有等待隊列,如果有則將自己加到等待隊列尾;

CountDownLatch countDownLatch = new CountDownLatch(5);
for(int i=0;i<5;i++){
  new Thread(new readNum(i,countDownLatch)).start();
}
countDownLatch.await();
System.out.println("線程執行結束。。。。");

Runnable類似() => {
  latch.countDown();
  System.out.println("線程組任務"+id+"結束,其他任務繼續");
}



CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () => {
   System.out.println("線程組執行結束");
});
for (int i = 0; i < 5; i++) {
    new Thread(new readNum(i,cyclicBarrier)).start();
}
Runnable類似() => {
  try {
    cyc.await();
    System.out.println("線程組任務" + id + "結束,其他任務繼續");
  } catch (Exception e) {
  }
}



Semaphore semaphore = new Semaphore(5);
類似
 semaphore.acquire();
 System.out.println("工人"+this.num+"佔用一個機器在生產...");
 Thread.sleep(2000);
 System.out.println("工人"+this.num+"釋放出機器");
 semaphore.release(); 

AQS核心思想:如果被請求的共享資源空閒,則將當前請求資源的線程設置爲有效的工作線程,並且將共享資源設置爲鎖定狀態。如果被請求的共享資源被佔用,那麼就需要一套線程阻塞等待以及被喚醒時鎖分配的機制,這個機制AQS是用CLH隊列鎖實現的,即將暫時獲取不到鎖的線程加入到隊列中。 AQS使用一個voliate int成員變量來表示同步狀態,通過內置的FIFO隊列來完成獲取資源線程的排隊工作。AQS使用CAS對該同步狀態進行原子操作實現對其值的修改。

AQS定義了兩種資源獲取方式:獨佔(只有一個線程能訪問執行,又根據是否按隊列的順序分爲公平鎖和非公平鎖,如ReentrantLock) 和共享(多個線程可同時訪問執行,如Semaphore/CountDownLatch,Semaphore、CountDownLatCh、 CyclicBarrier )。ReentrantReadWriteLock 可以看成是組合式,允許多個線程同時對某一資源進行讀。

AQS底層使用了模板方法模式, 自定義同步器在實現時只需要實現共享資源 state 的獲取與釋放方式即可,至於具體線程等待隊列的維護(如獲取資源失敗入隊/喚醒出隊等),AQS已經在上層已經幫我們實現好了。

8,ThredPoolExecutor 的參數有哪些?

可以問:線程隊列滿了會出現什麼情況,可不可以丟棄掉任務?(考:創建過程,以及拒絕策略)

(corePoolSize,maximumPoolSize,keepAliveTime, TimeUnit,
BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,
RejectedExecutionHandler handler)
1,沒達到corePoolSize,則創建新線程
2,到達之後,線程放入隊列,阻塞排隊
3,隊列滿後,沒達到maximumPoolSize,創建新線程
4,當線程空閒時間達到 keepAliveTime值時,線程會被銷燬
(默認>corePoolSize 才銷燬,allowCoreThreadTimeOut爲true時候,才銷燬corePool)
5,TreadFactory 創建線程的工程類。可以通過指定線程工廠爲每個創建出來的線程設置更有意義的名字
6,handler 執行拒絕策略的對象。當線程池的阻塞隊列已滿和指定的線程都已經開啓時。
   AbortPolicy: 直接拒絕所提交的任務,並拋出 RejectedExecutionException 異常;(默認)
   CallerRunsPolicy:只用調用者所在的線程來執行任務;
   DiscardPolicy:不處理直接丟棄掉任務;
   DiscardOldestPolicy:丟棄掉阻塞隊列中存放時間最久的任務,執行當前任務

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章