日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java自学之路-day17

發布時間:2024/9/21 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java自学之路-day17 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

JAVA17

多線程

進程和線程的概念

進程

l? 正在運行中的程序

l? 程序存儲在硬盤中 當進入內存運行時

l? 內存中的每一個程序就叫進程

l? 并且每一個進程都有一個獨立的功能

線程

l? 迅雷中的多線程下載

l? main方法中有很多方法一次排列

  • 如果其中一個方法執行了很多次循環
  • 那么下一個方法就不會執行
  • 從入口main到結束,一條路走到底 必須一個一個的執行
  • 這種程序是單線程程序
  • 效率慢
  • ?

    l? 例如

    多臺電腦網吧上網

    多條路通行

    線程

    概念

    l? CPU 中央處理器 inter AWD

    l? 四核心 八線程

    l? 360殺毒工具

  • 進入內存
  • 有一個進程 360safe.exe
  • 所有功能進入內存
  • 所有功能都是程序中的一個方法
  • 所有功能可以單獨同時運行
  • 所有功能由CPU運行
  • 每開啟一個功能 cpu就會開啟新的執行路徑
  • 也就是一個新的線程
  • 早期cpu一次只能執行一個線程 時間片輪回切換運行
  • 當前cpu有多核心 那么同一時刻就能執行多個線程
  • ?
  • ?

    迅雷下載

    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類 重寫run方法
  • 實現Runable接口 實現run方法
  • 實現線程繼承Thread

    l? 定義一個類繼承Thread 重寫run方法

    ?

    l? 在測試類中實例化這個類的對象 調用start方法

    ?

    ?

    l? Start方法只能執行一次

    l? 執行順序跟之前不一樣

    l? 圖解

  • Jvm開啟main主線程
  • cpu運行主線程
  • 運行中 方法中開了一個新線程
  • Cpu執行新線程
  • 繼續執行start方法啟動新線程 準備執行run方法
  • cpu有了兩個執行路徑
  • cpu自己控制運行main方法的循環還是run方法的循環
  • cpu分配時間片給線程
  • ?

    為什么要繼承Thread

    l? 調用run和start區別

  • Start開啟線程 并讓jvm調用run方法在開啟的線程中運行
  • run就是一個方法而已 等待被執行 沒有其他功能
  • 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()?

  • 需要在主線程中改名
  • main線程名改不了
  • ?

    l? 構造方法改線程名

  • 父類中有一個構造方法可以改名稱
  • ?

  • ?
  • ?

    Sleep方法

    l? 線程停止特定時間

    ?

    ?

    ?

    l? 拋異常

    因為休眠過程中被喚醒會拋此異常

    ?Runnable接口

    l? 實現線程的的另一種方式

    l? 實現接口Runnable

    l? 實現方法run

    示例

  • 先創建接口實現類
  • 然后創建Thread對象 傳遞實現類對象
  • 然后調用start方法
  • 原理

    ?

  • Thread有一個構造器方法 可以傳入Runnable類型對象
  • 定義一個類實現Runable接口 新建對象傳入Thread的構造方法中就可以開啟一個新線程運行代碼
  • 避免了單繼承局限性
  • 線程分為了兩個部分 一部分是線程對象 一部分是線程任務
  • 從而降低了耦合度
  • ?
  • 好處

    ?

    匿名內部類實現線程程序

    l? 前提 繼承或接口實現

    l? new 父類或者接口實現(){?? 重寫抽象方法???? }

    l? 示例

  • 繼承Thread
  • ?

  • ?實現接口
  • ?

    線程的狀態圖

    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類

  • Java.util.concurrent包
  • 方法
  • 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? 模擬示例

  • 執行前停頓一下 sleep
  • ?
  • ?

    解決

  • 同步代碼塊
  • 當一個線程進入數據操作是無論是否休眠 其他線程只能等待
  • Sun公司提供了一個技術實現了這樣的解決
  • 公式
  • Synchronzied(任意對象){

    ?? 線程操作的共享數據

    }

  • 同步代碼塊
  • 示例
  • ?

    不能寫匿名對象

    ?

    變得安全了

    ?

    但是速度變慢了

    執行原理

    l? 同步對象 任意對象

    l? 對象 :同步鎖 對象監視器

    l? 同步保證安全性 沒有鎖的線程不能執行 只能等

    l? 線程遇到同步代碼塊后 判斷同步鎖還有沒有

    l? 如果沒有就等待

    l? 如果有 獲取鎖? 將同步鎖設為0

    l? 進入同步代碼塊 此時如果休眠了

    l? 另一個線程過來 要執行代碼 會判斷同步鎖是否有 此時顯然是沒有的 因此就進不去代碼塊 不能執行代碼

    l? 此時如果第一個線程 喚醒了 就繼續執行代碼? 然后釋放同步鎖

    l? 因此一個線程需要判斷鎖 獲取鎖 釋放鎖 所以就延長了很長時間

    ?

    l? 同步鎖原理和上廁所

  • 對象就是廁所的門
  • 同步鎖就是廁所門的鎖
  • l? 多個線程訪問一個共享數據就要設置同步鎖

    同步方法

    l? 代碼簡潔

    l? 將線程共享數據和同步抽取到一個方法中

    ?

    l? 方法的聲明加上同步關鍵字 然后把同步不代碼塊刪除

    ?

    l? StringBuffer 就有這種同步方法 跑的慢

    ?

    l? StringBuilder 是線程不安全 跑的快

    ?

    l? 同步方法有鎖嗎?

  • 肯定有
  • 對象鎖是本類的對象引用 this
  • ?

    l? 如果方法是靜態的

  • 靜態方法中的鎖不是this本類對象引用
  • 靜態不屬于對象引用
  • 靜態方法中對象鎖是 本類類名.class
  • ?

    ?

  • 涉及到反射的原理
  • JDK1.5新特新 Lock接口

    l? 釋放同步鎖 看不到

    l? 如果代碼出現異常 鎖就不會釋放

    l? 因此JDK1.5后出現了Lock接口

    l? 此接口提供了比使用synchornized更多的方法和語句可獲得的跟廣泛的鎖定操作

    l? 示例

  • 接口方法
  • lock 獲取鎖

    unlock 釋放鎖

  • 實現類
  • ReentrantLock

  • 在成員變量 通過實現類創建lock接口的實現類對象
  • 在要鎖的代碼前 調用lock方法獲取鎖
  • 在要鎖的代碼后調用 unlock方法釋放鎖
  • 如果有異常在異常后面的finally代碼里面寫unclock 可保證異常出現時正常釋放鎖
  • 死鎖

    原理

    l? 同步鎖里面又寫了一個同步

    l? 程序中出現了無限等待

    l? 前提必須是多線程出現同步嵌套

    l? 線程進入同步獲取鎖 不出去同步不會釋放鎖

    l? 第一個人需要第二個人的鎖 第二個人有需要第第一個人的鎖

    l?

    模擬實現

    l? 定義兩個鎖對象 A B

  • 需要定義兩個類
  • 并且建立私有構造方法 是外類不能新建實例
  • 然后提供一個靜態final對象 讓外類直接使用 但不可更改
  • ?

    l? 循環用奇數偶數確定線程1 和線程2

    ?

    ?

    ?

    l? 然后一個測試類

  • 創建兩個線程來執行run方法
  • ?
  • ?

    l? 程序運行結果 程序永遠都不會停止運行

    ?

  • 前幾次都是搶占成功的
  • 最后兩次 第一次? 執行偶數循環,獲取了a鎖,但是還沒進入b 鎖,就被奇數循環搶占了,獲取了b鎖
  • 此時第一次需要b鎖才能繼續執行?? 第二次需要a鎖才能繼續執行
  • 那么此時誰都拿不到所需的資源 所以就死鎖了
  • 線程等待和喚醒

    概述

    l? 又叫線程通信

    l? 多個線程處理同一個資源

    l? 每個線程任務不一樣

    l? 如果要合理的運用資源

    l? 就需要通過一種手段使各個線程能有效的利用資源

    l? 這種手段就叫做 等待喚醒機制

    l? 比如售票 之前只是減票 現在有的線程需要加票

    示例

    l? 資源類

  • 定義公共兩個成員變量
  • ?

    l? 兩個線程類 輸入 輸出

  • 輸入
  • ?

  • 輸出
  • ?

    l? 測試類

    ?

    ?

    因為有兩個對象

    l? 解決

  • 死鎖 資源類中寫私有對象 讓外類通過調用新建實例
  • 在輸入類和輸入類中 寫一個可接受資源類對象的構造器
  • 然后在main方法中 新建一個資源類對象 傳入輸出類和輸入類的構造方法中
  • 結果
  • ?

  • 出現了性別亂套
  • l? 解決

  • 問題出現原理
  • a)???????? 輸入類搶到了cpu 進行賦值? 張三 男

    b)???????? 賦值 完 輸出沒有搶到cpu

    c)???????? 輸入類仍然搶到了cpu? 進行賦值 lisi

    d)???????? 剛賦值完lisi 還沒賦值nv

    e)???????? 輸出類搶到了cpu資源 就直接輸出 了 lisi nv

    f)????????? 此時就出現了 性別亂套

    ?

  • 解決
  • a)???????? 只有一種方法加同步鎖

    b)???????? 找共享數據

    c)???????? 在輸入類中加鎖

    ?

    輸出類加入鎖

    ?

    還是沒解決

    ?

    l? 解決

  • 原因
  • a)???????? 兩個線程是不是同一個鎖

  • 將對象鎖this改為對象鎖為 資源對象 r
  • 結果 解決了問題
  • ?

    案例分析

    l? 最終目標 一個輸入 一個輸出 交替出現

    l? 線程只會執行run方法 不分賦值和取值

    l? 理想狀態應該是 一次賦值一次打印

    l? 只有上一次賦值輸出后 下一次賦值才能開始

    l? 反過來 輸出一次后 必須等待下一次輸入完畢后才能進行輸出

    l? 實現步驟

  • 輸入:賦值后執行方法wait永遠等待
  • 輸出 變量值打印輸出后 notify輸入喚醒 然后輸出執行wait永遠等待
  • 輸入:被喚醒后,重新對變量賦值 賦值后必須喚醒輸出的線程botify 輸入wait
  • 實現

    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的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。