java自学之路-day17
JAVA17
多線程
進程和線程的概念
進程
l? 正在運行中的程序
l? 程序存儲在硬盤中 當進入內存運行時
l? 內存中的每一個程序就叫進程
l? 并且每一個進程都有一個獨立的功能
線程
l? 迅雷中的多線程下載
l? main方法中有很多方法一次排列
?
l? 例如
多臺電腦網吧上網
多條路通行
線程
概念
l? CPU 中央處理器 inter AWD
l? 四核心 八線程
l? 360殺毒工具
?
迅雷下載
l? 多線程下載
l? 并不是提高了網速 而是多線程提高了速度
?
線程的運行模式
分時調度
l? 所有線程輪流使用cpu資源 平均分配對個線程占用CPU時間
搶占式調度
l? 優先級高的多使用cpu資源 優先級相同的隨機選擇一個進行調度
l? ?
?
main主線程
l? 編譯
l? JVM運行main方法
l? 找操作系統 開線程
l? 對于cpu有了一個執行的路徑 運行方法main路徑有個名字main
l? 這個就是主線程
?
?
l? 多線程就算一條線程出現錯誤 其他線程也會執行
Thread類
概述
l? Java.lang包中
l? Jvm允許程序運行多個線程
l? 每一個線程都有一個優先級
l? 創建線程有兩個方法
實現線程繼承Thread
l? 定義一個類繼承Thread 重寫run方法
?
l? 在測試類中實例化這個類的對象 調用start方法
?
?
l? Start方法只能執行一次
l? 執行順序跟之前不一樣
l? 圖解
?
為什么要繼承Thread
l? 調用run和start區別
l? Thread是線程類 繼承這個類就是 線程類
l? 直接創建Thread類對象,run方法是這個類的方法,沒有任何操作 不能運行自定義的代碼 所以需要繼承這個類 重寫run方法然后執行我們需要在另一個線程中執行的代碼
l? Run方法的作用是為了執行我們要在新線程中執行的代碼
線程運行的內存圖
l? Main方法先進入
l? 然后調用start方法 run方法準備被jvm調用
l? Run方法不進入這個棧 會新開一個棧空間單獨執行run方法
l? ?
?
獲取線程名稱
l? main主線程名稱就是 main
l? 控制臺獲取默認線程名字
?
l? getName獲取線程名
?
調用父類方法可以不寫super
l? 獲取main線程名字
Static Thread currentThread();
獲取正在運行本方法的線程名字 返回Thread類型
?
簡化
?
設置線程名稱
l? setName()?
?
l? 構造方法改線程名
?
?
Sleep方法
l? 線程停止特定時間
?
?
?
l? 拋異常
因為休眠過程中被喚醒會拋此異常
?Runnable接口
l? 實現線程的的另一種方式
l? 實現接口Runnable
l? 實現方法run
示例
原理
?
好處
?
匿名內部類實現線程程序
l? 前提 繼承或接口實現
l? new 父類或者接口實現(){?? 重寫抽象方法???? }
l? 示例
?
?
線程的狀態圖
l? NEW?? 新建狀態?
?
l? RUNNABLE?? 運行狀態 正在JVM虛擬機中執行此線程
?
l? BLOCKED?? 受阻塞
死鎖 CPU資源被搶走
?
?
l? WAITTING??????? 等待 無限休眠
? Object類中的方法
?
l? TIMED_ WAITTING?? 休眠
?
l? TREMINATED 死亡狀態
?
l? 受阻塞具有cpu的執行資格 等待CPU的資源
l? 休眠等待 線程放棄CPU的執行資格
線程池
概述
l? 是一個容器可以存放多個線程
l? 程序一開始的時候 創建多個線程 存放到集合中
l? 使用時 用remove方法取出線程 使用完畢 再用add重新添加進去
l? 之前都是自己開發線程池
l? Jdk1.5之后添加了線程池技術
使用
使用線程池方式 Runable接口
l? 由線程池工廠創建
l? 再調用線程池中的方法創建線程
l? Executors類
a)???????? 創建多個
?
b)???????? 創建單個
?
c)???????? 返回值是線程池類對象
?
?
?
控制臺沒停止 線程用完后有回到了線程池
線程名字
?
停止線程
Shutdown 線程停止
實現線程Callable方法
l? Runnable接口 線程運行完沒有結果 不能拋異常
l? Jdk1.5后有個Callable接口 call方法 等同于run
l? call方法有返回值 可以拋異常?
l? 先用工廠類靜態方法newFixedRhreadPool創建線程池對象
l? 線程對象 調用方法submit提交線程任務 傳入一個Callable接口實現類
l? 示例
?
?
父類接口拋了異常 子類可拋異常也可不拋異常
練習
l? 異步計算
線程操作共享數據的安全問題
售票示例
l? 多個線程同時運行 同時運行某段代碼
l? 每次運行結果和單線程運行結果一樣
l? 售票
l? 多種方式購票 多個線程操作同一個數據
l? 此時應該數據同時更新 否則會出現安全問題
l? 示例
?
?
?
數據正常 但是存在安全隱患
安全問題引發
l? T0判斷完畢 準備開始操作
l? 此時cpu被t1線程搶占
l? T1判斷完畢 準備進行操作
l? 此時被t2線程搶占
l? T2判斷完畢 準備進行操作
l? 此時cpu資源獲得 t0執行操作 – 數據為0
l? T1也執行—數據為-1
l? T2也執行--數據為-2
l? 此時出現了線程安全問題
l? 模擬示例
?
解決
Synchronzied(任意對象){
?? 線程操作的共享數據
}
?
不能寫匿名對象
?
變得安全了
?
但是速度變慢了
執行原理
l? 同步對象 任意對象
l? 對象 :同步鎖 對象監視器
l? 同步保證安全性 沒有鎖的線程不能執行 只能等
l? 線程遇到同步代碼塊后 判斷同步鎖還有沒有
l? 如果沒有就等待
l? 如果有 獲取鎖? 將同步鎖設為0
l? 進入同步代碼塊 此時如果休眠了
l? 另一個線程過來 要執行代碼 會判斷同步鎖是否有 此時顯然是沒有的 因此就進不去代碼塊 不能執行代碼
l? 此時如果第一個線程 喚醒了 就繼續執行代碼? 然后釋放同步鎖
l? 因此一個線程需要判斷鎖 獲取鎖 釋放鎖 所以就延長了很長時間
?
l? 同步鎖原理和上廁所
l? 多個線程訪問一個共享數據就要設置同步鎖
同步方法
l? 代碼簡潔
l? 將線程共享數據和同步抽取到一個方法中
?
l? 方法的聲明加上同步關鍵字 然后把同步不代碼塊刪除
?
l? StringBuffer 就有這種同步方法 跑的慢
?
l? StringBuilder 是線程不安全 跑的快
?
l? 同步方法有鎖嗎?
?
l? 如果方法是靜態的
?
?
JDK1.5新特新 Lock接口
l? 釋放同步鎖 看不到
l? 如果代碼出現異常 鎖就不會釋放
l? 因此JDK1.5后出現了Lock接口
l? 此接口提供了比使用synchornized更多的方法和語句可獲得的跟廣泛的鎖定操作
l? 示例
lock 獲取鎖
unlock 釋放鎖
ReentrantLock
死鎖
原理
l? 同步鎖里面又寫了一個同步
l? 程序中出現了無限等待
l? 前提必須是多線程出現同步嵌套
l? 線程進入同步獲取鎖 不出去同步不會釋放鎖
l? 第一個人需要第二個人的鎖 第二個人有需要第第一個人的鎖
l?
模擬實現
l? 定義兩個鎖對象 A B
?
l? 循環用奇數偶數確定線程1 和線程2
?
?
?
l? 然后一個測試類
?
l? 程序運行結果 程序永遠都不會停止運行
?
線程等待和喚醒
概述
l? 又叫線程通信
l? 多個線程處理同一個資源
l? 每個線程任務不一樣
l? 如果要合理的運用資源
l? 就需要通過一種手段使各個線程能有效的利用資源
l? 這種手段就叫做 等待喚醒機制
l? 比如售票 之前只是減票 現在有的線程需要加票
示例
l? 資源類
?
l? 兩個線程類 輸入 輸出
?
?
l? 測試類
?
?
因為有兩個對象
l? 解決
?
l? 解決
a)???????? 輸入類搶到了cpu 進行賦值? 張三 男
b)???????? 賦值 完 輸出沒有搶到cpu
c)???????? 輸入類仍然搶到了cpu? 進行賦值 lisi
d)???????? 剛賦值完lisi 還沒賦值nv
e)???????? 輸出類搶到了cpu資源 就直接輸出 了 lisi nv
f)????????? 此時就出現了 性別亂套
?
a)???????? 只有一種方法加同步鎖
b)???????? 找共享數據
c)???????? 在輸入類中加鎖
?
輸出類加入鎖
?
還是沒解決
?
l? 解決
a)???????? 兩個線程是不是同一個鎖
?
案例分析
l? 最終目標 一個輸入 一個輸出 交替出現
l? 線程只會執行run方法 不分賦值和取值
l? 理想狀態應該是 一次賦值一次打印
l? 只有上一次賦值輸出后 下一次賦值才能開始
l? 反過來 輸出一次后 必須等待下一次輸入完畢后才能進行輸出
l? 實現步驟
實現
l? 為了保證程序執行 輸入首先拿到cpu執行權
l? 在資源類中加一個變量boolean flag
l? flage為真 說明賦值完成
l? flage為假 說明獲取值完成
l? 輸入 需要判斷標記 flage是否為真
如果為真? 則等待
如果為假 就進行賦值 并把標記改為false
l? 輸出也是如此
?
l? 示例
?
輸入
?
輸出
?
結果 拋出了異常
?
異常
?
就是說喚醒和等待方法 調用者錯了
應該是鎖對象 調用
修改
?
?
l? 結果
?
轉載于:https://www.cnblogs.com/DMYMaster/p/7293783.html
總結
以上是生活随笔為你收集整理的java自学之路-day17的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手摸手教你使用vue-cli脚手架-详细
- 下一篇: day6作业--游戏人生