java多線程詳解學習筆記

  程序:程序是指令和數據的有序集合,其本身沒有任何運行的含義,是一個靜態的概念。 

  進程:進程則是執行程序的一次執行過程,它是一個動態的概念。是系統資源分配的單位

  通常在一個進程中可以包含若干個線程,當然一個進程中至少有一個線程,不然沒有存在的意義。線程是 CPU調度和執行的單位。

  1、線程就是獨立的執行路徑

  2、在程序運行時,即使沒有自己創建線程,後臺也會有多個線程,如主線程,gc線程;

  3、main()稱之爲主線程,爲系統的入口,用於執行整個程序;

  4、在一個進程中,如果開闢了多個線程,線程的運行由調度器(CPU)安排調度,調度器是與操作系統緊密相關的,先後順序是不能人爲的干預的。

  5、對同一份資源操作時,會存在資源搶奪的問題,需要加入併發控制;

   創建線程方式一:   1、自定義線程類繼承Thread類

                                2、重寫run()方法,編寫線程執行體

                                3、創建線程對象,調用start()方法啓動線程

   總結:注意,線程開啓不一定立即執行,由CPU調度執行

    創建線程方式二:   1、自定義線程類實現Runnable接口

                                 2、重寫run()方法,編寫線程執行體

                                 3、創建線程對象,調用start()方法啓動線程(需要丟入runnable接口實現類,調用start方法)

   多個線程操作同一資源時會產生併發問題,引起數據紊亂。 

     創建線程方式三:1、實現Callable接口,需要返回值類型

                                  2、重寫call方法,需要拋出異常

                                  3、創建目標對象

                                  4、創建執行服務:ExecutorService ser = Executors.newFixedThreadPool(1) ;

                                  5、提交執行: Future<Boolean> result1 = ser.submit(t1);

                                  6、獲取結果: boolean r1 = result1.get()

                                  7、關閉服務: ser.shutdownNow();

   靜態代理模式總結:

   真實對象和代理對象都要實現同一個接口

   代理對象要代理真實角色,通過有參構造傳入

   好處:代理對象可以做很多真實對象做不了的事情

              真實對象專注做自己的事情     

   Lambda表達式:

   任何接口,如果只包含唯一一個抽象方法,那麼它就是一個函數式接口。

   (方法參數)->{主體};

    簡化1. 去掉參數類型

           2. 簡化括號

           3. 去掉花括號

    總結:lambda表達式只能有一行代碼的情況下才能簡化成爲一行,如果有多行,那麼就用代碼塊包裹。

               前提是接口爲函數式接口

               多個參數也可以去掉參數類型,要去掉就都去掉 ,必須加上括號。

   線程狀態:

   停止線程:不推薦使用JDK提供的stop()、destroy()方法。建議使用一個標誌位進行終止變量,當flag=false,則終止線程。

   線程休眠:sleep指定當前線程阻塞的毫秒數;每一個對象都有一個鎖,sleep不會釋放鎖;

                     模擬網絡延時:放大問題的發生性。

   線程禮讓:讓cpu重新調度,禮讓不一定成功!看CPU心情(Thread.yield())

   join合併線程,待此線程執行完成後,再執行其他線程,其他線程阻塞,可以想象成插隊

   觀測線程狀態:thread(線程對象).getState();
   java提供一個線程調度器來監控程序中啓動後進入就緒狀態的所有線程,線程調度器按照優先級決定應該調度哪個線程來執行。

   線程的優先級用數字表示,範圍 從1~10   線程對象.setPriority()  設置線程優先級 不設置默認優先級爲5

   優先級的設定建議在start()調度前,優先級低只是意味着獲得調度的概率低,並不是優先級低就不會被調用了,這都得看cpu

   守護線程: 線程分爲用戶線程和守護線程  

                      虛擬機必須確保用戶線程執行完畢(main())

                      虛擬機不用等待守護線程執行完畢(gc())

                      thread.setDaemon(true或false)  默認是false表示用戶線程,正常的線程都是用戶線程

   併發:同一個對象被多個線程同時操作

   線程同步:形成條件:隊列+鎖 (synchronized)       

   synchronized  默認鎖的是this 同步方法和同步塊

   public synchronized 返回值類型 方法名() {

   }

   synchronized(對象){  //鎖的對象就是變化的量,需要增刪改的對象

     可能發生線程安全問題的代碼   

   }

   JUC安全類型的集合:  CopyOnWriteArrayList

   死鎖:兩個或多個線程各自佔有一些資源,都在等待對方釋放資源,都停止執行的情況,某一個同步塊同時擁有"兩個以上對象的鎖"時,就可能發生"死鎖"的問題。(簡單來說就是多個線程互相抱着對方需要的資源,然後形成僵持)

   產生死鎖的四個必要條件:

     1.互斥條件:一個資源每次只能被一個進程使用。

     2.請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。

     3.不剝奪條件:進程已獲得的資源,在未使用完之前,不能強行剝奪。

     4.循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關係。

     Lock鎖:和synchronized差不多的東西,Lock是顯式鎖(手動開啓和關閉鎖,別忘關閉鎖)  synchronized是隱式鎖,出來作用域自動釋放  ReentrantLock(可重入鎖)

     線程通信:wait() 表示線程一直等待,直到其他線程通知,與sleep不同,會釋放鎖

                       notify() 喚醒一個處於等待狀態的線程

     生產者消費者模型 -->  利用緩衝區解決:管程法 信號燈法

     線程池:提前創建好多個線程,放入線程池中,使用時直接獲取,使用完放回池中。可以避免頻繁創建銷燬、實現重複利用。類似生活中的公共交通工具。  

     創建服務,創建線程池,參數爲線程池大小

     ExecutorService ser = Executors.newFixedThreadPool(10) ;

     執行

     ser.execute(接口的實現類對象);

     關閉連接

     ser.shutdown();

    

   

 

 

     

 

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