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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

CoreJava 笔记总结-第十二章 并发-1

發(fā)布時間:2023/12/4 java 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CoreJava 笔记总结-第十二章 并发-1 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第十二章 并發(fā)

線程

package chapter12_concurrent.threads;public class ThreadsTest {public static final int DELAY = 10;public static final int STEPS = 100;public static final double MAX_AMOUNT = 1000;public static void main(String[] args) {var bank = new Bank(4, 100000);//Runnalbe 是一個函數式接口,可以用一個lambda表達式創(chuàng)建一個實例Runnable task1 = () -> {try {for (int i = 0; i < STEPS; i++) {double amount = MAX_AMOUNT * Math.random();bank.transfer(0, 1, amount);Thread.sleep((long) (DELAY * Math.random()));}} catch (InterruptedException e) {}};Runnable task2 = () -> {try {for (int i = 0; i < STEPS; i++) {double amount = MAX_AMOUNT * Math.random();bank.transfer(2, 3, amount);//休眠制定的毫秒數Thread.sleep((long) ( DELAY * Math.random()));}} catch (InterruptedException e) {}};//構造一個Thread對象,啟動線程new Thread(task1).start();new Thread(task2).start();} }

線程狀態(tài)

  • New, Runnable, Blocked, Waiting, Timed waiting, Terminated

分別表示線程的六種狀態(tài): 新建, 可運行, 阻塞, 等待, 計時等待, 終止


新建線程

  • new Thread(r) 新建線程, 但是還沒有開始運行

可運行線程

  • 調用start方法后線程就屬于可運行狀態(tài), 處于runnable可能運行也可能沒有運行

阻塞和等待進程

  • 線程處于阻塞和等待狀態(tài)不活動,不運行任何代碼,消耗最少資源
  • 當線程試圖獲取一個內部的對象鎖,而該鎖目前被其他線程占有,該線程就會被阻塞.所有其他線程釋放這個鎖,并且線程調度器允許該線程持有這個鎖,他將變成非阻塞狀態(tài)
  • 當線程等待另一個線程通知調度器出現一個條件時,這個線程會進入等待狀態(tài)
  • 有的方法有超時參數,調用這些方法會讓線程進入計時等待狀態(tài).這一狀態(tài)會一直等待到超時期滿或者接收到適當的通知

終止線程

  • run方法正常退出
  • 一個沒有捕獲的異常終止了run方法

線程屬性

中斷線程

  • interrupt方法可以用來請求終止一個線程,程序調用該方法就會設置線程中斷狀態(tài)
  • 測試是否設置了中斷狀態(tài):Thread.currentThread()獲得當前線程
while(!Thread.currentThread().isInterrupted()){... }
  • 線程被阻塞就無法檢查中斷狀態(tài)

  • 當在一個被sleep, wait調用的阻塞的線程上調用interrupt方法,那個阻塞調用將被一個InterruptedException異常中斷

  • 一般將中斷解釋為一個中止請求

  • 如果循環(huán)調用了sleep,不要檢測中斷狀態(tài),應當捕獲InterruptedException

  • interrupted: 靜態(tài)方法, 檢查當前線程是否中斷,并且清楚線程中斷狀態(tài)

  • isInterrupted: 實例方法, 檢查是否有線程被中斷,不改變中斷狀態(tài)

  • 不要抑制InterruptedException異常:

    • catch子句中調用Thread.currentThread().interrupt()設置中斷狀態(tài),調用者就可以檢查中斷狀態(tài)了

    • void mySubTask(){...try{sleep(delay);}catch(InterruptedException e){Thread.currentThread().interrupt()} }
    • 更好的是,標記方法,去掉try語句塊

    • void mySubTask() throw InterruptedException { ... sleep(delay); }

守護線程

  • t.setDaemon(true);
  • 守護線程唯一作用就是為其他線程提供服務

線程名

  • 默認狀態(tài)下有容易記憶的名字
  • 改名:setName(...)

未捕獲異常的處理器

  • 線程組ThreadGroup類實現了Thread.UncaughtExceptionHandler接口,其uncaughtException方法執(zhí)行以下操作:
  • 該線程若有父線程那么調用父線程的uncaughtException方法
  • 如果Thread.getDefaultExceptionHandler方法返回一個非null處理器,調用該處理器
  • 否則,如果Throwable類是ThreadDeath的一個實例,什么也不做
  • 否則將線程的名字和Throwable棧軌跡輸出到System.err

線程的優(yōu)先級

  • setPriority方法提高或者降低任何一個線程的優(yōu)先級
  • MIN_PRIORITY(1), NORM_PRIORITY(5), MAX_PRIORITY(10)

同步

  • 競態(tài)條件: 兩個及以上線程共享對同一組數據的存取, 線程相互覆蓋導致對象破壞
  • 不同步的操作:
package chapter12_concurrent.unsynch;public class UnsynchBankTest {public static final int NACCOUNT = 100;public static final double INITIAL_BALANCE = 1000;public static final double MAX_AMOUNT = 1000;public static final int DELAY = 10;public static void main(String[] args) {var bank = new Bank(NACCOUNT, INITIAL_BALANCE);for (int i = 0; i < NACCOUNT; i++) {int fromAccount = i;Runnable r = () -> {try {while (true) {int toAccount = (int) (bank.size() * Math.random());double amount = MAX_AMOUNT * Math.random();bank.transfer(fromAccount, toAccount, amount);Thread.sleep((int) (DELAY * Math.random()));}} catch (InterruptedException e) {}};var t = new Thread(r);t.start();}} }

鎖對象

  • 兩種機制可以防止并發(fā)訪問代碼塊: synchronized, ReentrantLock
  • 基本結構:
mylock.lock(); try{critical section } finally{myLock.unlock(); }
  • 該結構確保任何時刻只有一個線程進入臨界區(qū),一旦一個線程鎖定了鎖對象,其他任何線程無法通過lock語句
  • 要把unlock放入finally語句.如果臨界區(qū)代碼異常,鎖必須釋放,否則線程永遠阻塞
public class bank{private ReentrantLock bankLock = new ReentrantLock();......public void transfer(int from, int to, double amount){bankLock.lock();try {if (accounts[from] < amount) return;System.out.print(Thread.currentThread());accounts[from] -= amount;System.out.printf(" %10.2f from %d to %d", amount, from, to);accounts[to] += amount;System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());}finally {bankLock.unlock();}} }
  • 每個bank有自己的ReentrantLock對象,兩個線程視圖訪問同一個bank對象,鎖可以用來保證串行化訪問
  • 兩個線程訪問不同的bank對象,每個線程會得到不同的鎖對象,線程不會阻塞

條件對象

  • 下面的Bank類加入了鎖對象, 保護金額轉賬不夠時候線程覆蓋的情況
  • 引入了條件對象, 調用await方法將當前線程暫停,放棄鎖,允許其他線程執(zhí)行
  • 另一個線程完成轉賬后調用signalAll重新激活等待這個條件的所有線程
  • 其中的某個線程將從await調用處返回得到這個鎖,繼續(xù)執(zhí)行之前暫停的地方
package chapter12_concurrent.synch;import java.util.*; import java.util.concurrent.locks.*;public class Bank {private final double[] accounts;private ReentrantLock banklock;private Condition sufficientFunds;public Bank(int n, double initialBalance) {accounts = new double[n];Arrays.fill(accounts, initialBalance);banklock = new ReentrantLock();sufficientFunds = banklock.newCondition();}public void transfer(int from, int to, double amount) throws InterruptedException{banklock.lock();try {while (accounts[from] < amount) {sufficientFunds.await();}System.out.println(Thread.currentThread());accounts[from] -= amount;System.out.printf(" %10.2f from %d to %d.", amount, from, to);accounts[to] += amount;System.out.printf(" Total balance: %10.2f%n", getTotalBanlance());sufficientFunds.signalAll();}finally {banklock.unlock();}}public double getTotalBanlance() {banklock.lock();try {double sum = 0.0;for (double a: accounts)sum += a;return sum;}finally {banklock.unlock();}}public int size() {return accounts.length;} }

總結

以上是生活随笔為你收集整理的CoreJava 笔记总结-第十二章 并发-1的全部內容,希望文章能夠幫你解決所遇到的問題。

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