執行緒-集合-反射

邏輯howe發表於2020-11-26

執行緒

注意!java並不能直接開啟執行緒,java無法操作硬體,檢視thread原始碼可以知道,它是通過呼叫一個本地c++方法實現的。

實現方式
  • 通過繼承thread類實現(擴充性不強,繼承thread後就不能繼承其他類了)

  • 通過實現Runnable介面實現

  • 實現callable類(企業級開發中常用,特點是重寫的call()方法有返回值,有利於異常處理)

如何使用?
  1. 自定義類繼承thread類或實現介面
  2. 重寫run方法,編寫執行體
  3. 新建執行緒例項,start()啟動
//繼承Thread類啟動
Thread thread = new Thread(執行緒類);	  //建立執行緒例項
thread.setName("執行緒名稱");				  //一種規範
thread.start();							//啟動

//實現Runnable介面啟動
new Thread(傳入物件,"執行緒名稱").start();		//啟動
並行與併發
  • 並行:多人同行,多個執行緒同時執行,多核處理

  • 併發:多個執行緒呼叫一個資源,通過快速交替執行模擬並行狀態

執行緒與程式
  • 程式:如qq,微信,Typora等

  • 執行緒:比如Typora裡定時自動更新的功能便是執行緒實現

  • 一個程式包括多個執行緒,至少一個,java預設兩個執行緒,main執行緒與GC執行緒

執行緒的五個狀態

建立,就緒,執行,阻塞,死亡

在這裡插入圖片描述

new					#建立
runnable			#執行
blocked				#阻塞
waiting				#等待(等到為止)
time_waiting		#超時等待(超過時間不再等待)
terminated			#終止

Thread.getstate()	#獲取執行緒狀態,以上6個
while(thread.getstate() != Thread.State.TERMINATED);		#注意TERMINATED狀態的執行緒無法再次啟動
wait/sleep
  • wait:等待會釋放鎖,只能在同步程式碼塊中使用(加鎖的方法),繼承object類,需要捕獲異常
  • sleep:抱著鎖睡覺,不會釋放鎖,在哪裡都可以睡,繼承至thread類
  • 企業級開發中並不使用sleep,而是呼叫JUC的timeUnit方法
執行緒禮讓yield
  • 將執行緒的執行狀態改為就緒狀態
  • 禮讓不一定成功,看cpu心情
  • 方法Thread.yield()
執行緒插隊Join
  • 插入執行緒後,執行完該執行緒再恢復原來的狀態,如同插隊打飯
  • 方法Thread.yield()
執行緒優先順序
  • 使用數字1~10表示執行緒的優先順序,預設優先順序為5
  • getPriority()和setPriiority()提供對執行緒的優先順序獲取和設定的方法
  • 注意優先順序高的不是一定先執行,而是增加了先執行的概率,優先順序的設定建議在start前
守護執行緒
  • 執行緒分使用者執行緒(如main執行緒,預設執行緒都是守護執行緒)和守護執行緒(如gc垃圾回收執行緒)
  • 虛擬機器必須確保使用者執行緒執行結束,而不需要等待守護執行緒結束
  • thread.setDaemon(true)設定為守護執行緒,預設false使用者執行緒,start前設定
  • 守護執行緒常用於日誌,監控記憶體,垃圾回收等
執行緒同步
  • 一個物件被多個執行緒訪問,即執行緒同步
  • 保證併發安全性條件:佇列+鎖
  • 實現執行緒同步使用排隊機制,建立等待池
synchronized 鎖(同步方法)
  • 加鎖能保證安全性,但降低了效能,且破壞執行緒的優先順序
  • 使用synchronized鎖的是this,或者說class,我們往往需要鎖的是物件,建議使用同步塊synchronized(obj){ },這裡obj是要上鎖的物件,被稱之為同步監視器。
Lock鎖
  • jdk5開始出現的方法,繼承於JUC

  • 相比於隱式鎖synchronized,lock鎖是顯示的,手動進行加鎖解鎖

  • lock鎖執行效率上高於synchronized,且有很多子類,有更好的擴充性

  • lock是程式碼塊鎖,不能對方法或者類上鎖

  • ReentrantLock可重入鎖的使用

    public TestLock implements Runnable{
        //票的總數
        private tickNums = 10;
        //定義lock鎖
        private final ReentrantLock lock = new ReentrantLock();
        
        @Override
        public void run() {
            while (true) {
                try {
                    lock.lock();		//加鎖
                    Thread.sleep(1000)	//休眠1秒
                    System.out.println(tickNums--);
                } finally {
                    lock.unlock();		//解鎖
                }
            }
        }
    }
    
執行緒協調(生產者消費者問題)
  • 管程法:建立緩衝區,充當倉庫的角色,產品不足通知生產者,有了產品通知消費者

  • 訊號燈法:設定識別符號,通過狀態通知生產者消費者

  • 常用關鍵字

    wait()				//釋放資源開始等待,進入等待池
    wait(long timecut)	//指定時間等待,單位毫秒
    notify()			//隨機喚醒一個等待池(同一個物件上呼叫wait()方法的中的執行緒
    notifyAll()			//喚醒同一個物件上所有呼叫wait()方法的執行緒,根據優先順序呼叫
    
執行緒併發庫
  • 目的是設定執行緒數量上限,防止執行緒過多導致緩慢或崩潰,執行緒池控制執行緒的建立與銷燬

  • 建立執行緒池有常用的四種執行緒池,通過JUC的Excutors提供方法

    newFixdThreadPool()			//指定最大併發數,超出的在佇列中等待
    newCachedThreadPool()		//可緩衝執行緒池,長久不用的(60s)自動回收
    newScheduledThreadPool()	//指定最大併發數,可執行週期性,定時性任務執行
    newSingleThreadExecutor()	//單執行緒化的執行緒池
    
  • 執行緒池使用方式

    ExecutorService service = Excutors.newFixdThreadPool(10)			//建立執行緒池連線,包含10個執行緒
    
    //執行
    service.excute(new Mythread());
    service.excute(new Mythread2());
    .......
        
    service.shutdown();													//關閉連線
    

集合

存放物件的容器,容量可變,注意集合裡存放的都是物件的引用,不能存放基本資料型別,基本資料型別要進行包裝後才能存入。

集合框架

在這裡插入圖片描述

Collection

儲存的都是value型別的

List

有序的,有下標,可重複,可為null

  • ArrayList

    • 底層是陣列實現,可自動擴容,一般是裝滿0.75擴容0.5倍

    • 查詢,修改效率高,插入,刪除效率低

    • 預設是執行緒不安全的,可以設定為執行緒安全

      List lsit = Collections.synchronizedList(new ArrayList());

  • LinkedList

    • 底層用雙向連結串列實現的

    • 插入,刪除高效,查詢,修改低效

    • 執行緒不安全的

  • Vector

    • 向量,可以理解為ArrayList()的同步實現
Set

不可重複

  • HashSet

    • 底層使用HashMap實現的
    • 無序,可有一個null
    • 初始容量16
  • TreeSet

    • 底層使用TreeMap實現的
    • 插入時排序,不可為null
    • 一個不同步的非執行緒安全的二叉樹

Map

存放key-value型別的鍵值對

HashMap
  • 底層由Hash表(陣列結構)+連結串列實現的,jdk8後,預設長度為8時實現紅黑樹可排序

  • key無序的,不可重複,可有一個null,value無限制(判斷key重複先比hashCode值,再呼叫equals()對比內容)

  • 預設執行緒不安全的

  • HashTable與Hashmap類似,是執行緒安全的,但效率會降低

  • ConcurrentHashMap是用兩者實現的,執行緒安全且效率高

TreeMap
  • 底層通過紅黑樹實現
  • 預設key自然順序排序,不可重複,不能為null
  • 可被克隆,可序列化

反射

所有框架底層的實現機制就是反射+註解

概述
  • 理解:
    在這裡插入圖片描述

  • java作為一門靜態語言,因為有了反射,讓它可以實現動態語言的功能,讓java變成一門準靜態語言

  • 使用反射機制,允許我們在程式執行期間操作類的內部資訊,包括私有化屬性,方法(所以java不存在真正意義上的封裝)

  • 反射會消耗大量的效能,大概是new的幾十倍,使用需要謹慎

Class
  • 不管建立多少個類的例項,jvm中都只有一個它的Class,例如我們寫了一個類,如果沒有new一個物件例項化,是沒有生成.class檔案的,只有我們程式中例項化了物件,且不管例項化多少個,都只有一個對應的.class檔案。

  • 通過Class可以獲得這個類的所有內部資訊,結構

  • 幾乎所有型別都有Class物件,包括介面,[]陣列,enum列舉,註解,基本資料型別,甚至void都有Class物件

  • 獲取Class例項

    //com.howe.entity下定義一個Student類繼承Person類
    Person person = new Student();
    
    //方法一:通過例項物件獲取Class
    Class c1 = person.getClass();
    
    //方法二:通過forname獲取Class
    Class c2 = Class.forname("com.howe.entity.Student");		//需要丟擲異常
        
    //方法三:通過類名.class屬性獲取
    Class c3 = Student.class;
    
    //方法四:一些類(如基本資料型別的封裝類)可以通過.TYPE獲取
    Class c4 = Integer.TYPE
        
    //獲取Class父類的Class
    Class c5 = c1.getSuperclass();
    

相關文章