程序:程序是指令和數據的有序集合,其本身沒有任何運行的含義,是一個靜態的概念。
進程:進程則是執行程序的一次執行過程,它是一個動態的概念。是系統資源分配的單位
通常在一個進程中可以包含若干個線程,當然一個進程中至少有一個線程,不然沒有存在的意義。線程是 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();