日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Java 并發(fā)學習筆記總結

瀏覽:150日期:2022-09-05 16:10:20
并發(fā)

最近重新復習了一邊并發(fā)的知識,發(fā)現自己之前對于并發(fā)的了解只是皮毛。這里總結以下Java并發(fā)需要掌握的點。

使用并發(fā)的一個重要原因是提高執(zhí)行效率。由于I/O等情況阻塞,單個任務并不能充分利用CPU時間。所以在單處理器的機器上也應該使用并發(fā)。為了實現并發(fā),操作系統(tǒng)層面提供了多進程。但是進程的數量和開銷都有限制,并且多個進程之間的數據共享比較麻煩。另一種比較輕量的并發(fā)實現是使用線程,一個進程可以包含多個線程。線程在進程中沒有數量限制, 數據共享相對簡單。線程的支持跟語言是有關系的。Java 語言中支持多線程。

Java 中的多線程是搶占式的。這意味著一個任務隨時可能中斷并切換到其它任務。所以我們需要在代碼中足夠的謹慎,防范好這種切換帶來的副作用。

基礎

Runnable它可以理解成一個任務。它的run()方法就是任務的邏輯,執(zhí)行順序。

Thread它是一個任務的載體,虛擬機通過它來分配任務執(zhí)行的時間片。Thread中的start方法可以作為一個并發(fā)任務的入口。不通過start方法來執(zhí)行任務,那么run方法就只是一個普通的方法

線程的狀態(tài)有四種:

NEW 線程創(chuàng)建的時候短暫的處于這種狀態(tài)。這種狀態(tài)下已經可以獲得CPU時間了,隨后可能進入RUNNABLE,BLOCKED狀態(tài)。RUNNABLE 此狀態(tài)下只要CPU將時間分配給線程,線程中的任務就可以執(zhí)行。隨后可能進入BLOCKED,DEAD狀態(tài)。BLOCKED 線程可以運行,但是有某個條件阻止著它。當線程處于阻塞狀態(tài)時,CPU不會分配時間片給它,直到它重新進入RUNNABLE狀態(tài)。DEAD 此狀態(tài)的線程將永遠不會獲得CPU時間片。通常是因為run()方法返回才會到達此狀態(tài)。此時任務還是可以被中斷的。

Callable<T>它是一個帶返回的異步任務,返回的結果放到一個Future對象中。

Future<T>它可以接受Callable任務的返回結果。在任務沒有返回的時候調用get方法會阻塞當前線程。cancel方法會嘗試取消未完成的任務(未執(zhí)行->直接不執(zhí)行,已經完成->返回false,正在執(zhí)行->嘗試中斷)。

FutureTask<T>同時繼承了Runnable, Callable 接口。

Java 1.5之后,不再推薦直接使用Thread對象作為任務的入口。推薦使用Executor管理Thread對象。Executor是線程與任務之間的的一個中間層,它屏蔽了線程的生命周期,不再需要顯式的管理線程。并且ThreadPoolExecutor 實現了此接口,我們可以通過它來利用線程池的優(yōu)點。

線程池涉及到的類有:Executor,ExecutorService,ThreadExecutorPool,Executors,FixedThreadPool,CachedThreadPool,SingleThreadPool。

Executor只有一個方法,execute來提交一個任務

ExecutorService提供了管理異步任務的方法,也可以產生一個Future對象來跟蹤一個異步任務。

主要的方法如下:

submit可以提交一個任務shutdown可以拒絕接受新任務shutdownNow可以拒絕新任務并向正在執(zhí)行的任務發(fā)出中斷信號invokeXXX批量執(zhí)行任務

ThreadPoolExecutor線程池的具體實現類。線程池的好處在于提高效率,能避免頻繁申請/回收線程帶來的開銷。

它的使用方法復雜一些,構造線程池的可選參數有:

corePoolSize : int 工作的Worker的數量。maximumPoolSize : int 線程池中持有的Worker的最大數量keepAliveTime : long 當超過Workder的數量corePoolSize的時候,如果沒有新的任務提交,超過corePoolSize的Worker的最長等待時間。超過這個時間之后,一部分Worker將被回收。unit : TimeUnit keepAliveTime的單位workQueue : BlockingQueue 緩存任務的隊列, 這個隊列只緩存提交的Runnable任務。threadFactory : ThreadFactory 產生線程的“工廠”handler : RejectedExecutionHandler 當一個任務被提交的時候,如果所有Worker都在工作并且超過了緩存隊列的容量的時候。會交給這個Handler處理。Java 中提供了幾種默認的實現,AbortPolicy, CallerRunsPolicy, DiscardOldestPolicy, DiscardPolicy。

這里的Worker可以理解為一個線程。

這里之前想不通,覺得線程不可能重新利用綁定新任務。看了下源碼發(fā)現原來確實不是重新綁定任務。每一個Worker的核心部分只是一個循環(huán),不斷從緩存隊列中取任務執(zhí)行。這樣達到了重用的效果。

final void runWorker(Worker w) { Runnable task = w.firstTask; // ... try { while(task != null || (task=getTask())!=null) { try{task.run(); } catch(Exception e){ } // ... } } finally { // ... } // ... }

Executors類提供了幾種默認線程池的實現方式。

CachedThreadExecutor工作線程的數量沒有上限(Integer的最大值), 有需要就創(chuàng)建新線程。FixedThreadExecutor預先一次分配固定數量的線程,之后不再需要創(chuàng)建新線程。SingleThreadExecutor只有一個線程的線程池。如果提交了多個任務,那么這些人物將排隊,每個任務都在上一個人物執(zhí)行完之后執(zhí)行。所有任務都是按照它們的提交順序執(zhí)行的。

sleep(long)當前線程 中止 一段時間。它不會釋放鎖。Java1.5之后提供了更加靈活的版本。

TimeUnit可以指定睡眠的時間單位。

優(yōu)先級 絕大多數情況下我們都應該使用默認的優(yōu)先級。不同的虛擬機中對應的優(yōu)先級級別的總數,一般用三個就可以了MAX_PRIORITY,NORM_PRIORITY,MIN_PRIORITY。

讓步 Thread.yield()建議相同優(yōu)先級的其它線程先運行,但是不保證一定運行其它線程。

后臺線程 一個進程中的所有非后臺線程都終止的時候整個進程也就終止,同時殺死所有后臺線程。與優(yōu)先級沒有什么關系。

join() 線程 A 持有線程T,當在線程T調用T.join()之后,A會阻塞,直到T的任務結束。可以加一個超時參數,這樣在超時之后線程A可以放棄等待繼續(xù)執(zhí)行任務。

捕獲異常 不能跨線程捕獲異常。比如說不能在main線程中添加try-catch塊來捕獲其它線程中拋出的異常。每一個Thread對象都可以設置一個UncaughtExceptionHandler對象來處理本線程中拋出的異常。線程池中可以通過參數ThreadFactory來為每一個線程設置一個UncaughtExceptionHandler對象。

訪問共享資源

在處理并發(fā)的時候,將變量設置為private非常的重要,這可以防止其它線程直接訪問變量。

synchronized修飾方法在不加參數情況下,使用對象本身作為鎖。靜態(tài)方法使用Class對象作為鎖。同一個任務可以多次獲得對象鎖。

顯式鎖 Lock,相比synchronized更加靈活。但是需要的代碼更多,編寫出錯的可能性也更高。只有在解決特殊問題或者提高效率的時候才用它。

原子性 原子操作就是永遠不會被線程切換中斷的操作。很多看似原子的操作都是非原子的,比如說long,double是由兩個byte表示的,它們的所有操作都是非原子的。所以,涉及到并發(fā)異常的地方都加上同步吧。除非你對虛擬機十分的了解。

volatile 這個關鍵字的作用在于防止多線程環(huán)境下讀取變量的臟數據。這個關鍵字在c語言中也有,作用是相同的。

原子類 AtomicXXX類,它們能夠保證對數據的操作是滿足原子性的。這些類可以用來優(yōu)化多線程的執(zhí)行效率,減少鎖的使用。然而,使用難度還是比較高的。

臨界區(qū) synchronized關鍵字的用法。不是修飾整個方法,而是修飾一個代碼塊。它的作用在于盡量利用并發(fā)的效率,減少同步控制的區(qū)域。

ThreadLocal 這個概念與同步的概念不同。它是給每一個線程都創(chuàng)建一個變量的副本,并保持副本之間相互獨立,互不干擾。所以各個線程操作自己的副本,不會產生沖突。

終結任務

這里我講一下自己當前的理解。

一個線程不是可以隨便中斷的。即使我們給線程設置了中斷狀態(tài),它也還是可以獲得CPU時間片的。只有因為sleep()方法而阻塞的線程可以立即收到InterruptedException異常,所以在sleep中斷任務的情況下可以直接使用try-catch跳出任務。其它情況下,均需要通過判斷線程狀態(tài)來判斷是否需要跳出任務(Thread.interrupted()方法)。

synchronized方法修飾的代碼不會在收到中斷信號后立即中斷。ReentrantLock鎖控制的同步代碼可以通過InterruptException中斷。

Thread.interrupted方法調用一次之后會立即清空中斷狀態(tài)。可以自己用變量保存狀態(tài)。

線程協(xié)作

wait/notifyAll wait/notifyAll是Object類中的方法。調用wait/notifyAll方法的對象是互斥對象。因為Java中所有的Object都可以做互斥量(synchronized關鍵字的參數),所以wait/notify方法是在Object類中的。

wait與sleep 不同在于sleep方法是Thread類中的方法,調用它的時候不會釋放鎖;wait方法是Object類中的方法,調用它的時候會釋放鎖。

調用wait方法之前,當前線程必須持有這段邏輯的鎖。否則會拋出異常,不能繼續(xù)執(zhí)行。

wait方法可以將當前線程放入等待集合中,并釋放當前線程持有的鎖。此后,該線程不會接收到CPU的調度,并進入休眠狀態(tài)。有四種情況肯能打破這種狀態(tài):

有其它線程在此互斥對象上調用了notify方法,并且剛好選中了這個線程被喚醒;有其它線程在此互斥對象上調用了notifyAll方法;其它線程向此線程發(fā)出了中斷信號;等待時間超過了參數設置的時間。

線程一旦被喚醒之后,它會像正常線程一樣等待之前持有的所有鎖。直到恢復到wait方法調用之前的狀態(tài)。

還有一種不常見的情況,spurious wakeup(虛假喚醒)。就是在沒有notify,notifyAll,interrupt的時候線程自動醒來。查了一些資料并沒有弄清楚是為什么。不過為了防止這種現象,我們要在wait的條件上加一層循環(huán)。

當一個線程調用wait方法之后,其它線程調用該線程的interrupt方法。該線程會喚醒,并嘗試恢復之前的狀態(tài)。當狀態(tài)恢復之后,該線程會拋出一個異常。

notify 喚醒一個等待此對象的線程。notifyAll 喚醒所有等待此對象的線程。

錯失的信號

當兩個線程使用notify/wait或者notifyAll/wait進行協(xié)作的時候,不恰當的使用它們可能會導致一些信號丟失。例子:

T1: synchronized(shareMonitor){ // set up condition for T2 shareMonitor.notify();}T2: while(someCondition){ // Point 1 synchronized(shareMonitor){shareMonitor.wait(); }}

信號丟失是這樣發(fā)生的:

當T2執(zhí)行到Point1的時候,線程調度器將工作線程從T2切換到T1。T1完成T2條件的設置工作之后,線程調度器將工作線程從T1切換回T2。雖然T2線程等待的條件已經滿足,但還是會被掛起。

解決的方法比較簡單:

T2: synchronized(sharedMonitor) { while(someCondition) {sharedMonitor.wait(); }}

將競爭條件放到while循環(huán)的外面即可。在進入while循環(huán)之后,在沒有調用wait方法釋放鎖之前,將不會進入到T1線程造成信號丟失。

notify & notifyAll 前面已經提過這兩個方法的區(qū)別。notify是隨機喚醒一個等待此鎖的線程,notifyAll是喚醒所有等待此鎖的線程。

Condition 他是concurrent類庫中顯式的掛起/喚醒任務的工具。它是真正的鎖(Lock)對象產生的一個對象。其實用法跟wait/notify是一致的。await掛起任務,signalAll()喚醒任務。

生產者消費者隊列 Java中提供了一種非常簡便的容器,BlockingQueue。已經幫你寫好了阻塞式的隊列。

除了BlockingQueue,使用PipedWriter/PipedReader也可以方便的在線程之間傳遞數據。

死鎖

死鎖有四個必要條件,打破一個即可去除死鎖。

四個必要條件:

互斥條件。 互斥條件:一個資源每次只能被一個進程使用。請求與保持條件:一個線程因請求資源而阻塞時,對已獲得的資源保持不放。不剝奪條件:線程已獲得的資源,在末使用完之前,不能強行剝奪。循環(huán)等待條件:若干線程之間形成一種頭尾相接的循環(huán)等待資源關系。

本來自己翻譯,但發(fā)現百度上描述的更好一些,直接copy到這里來,并把進程換成了線程。

其它工具

CountDownLatch同步多個任務,強制等待其它任務完成。它有兩個重要方法countDown,await以及構造時傳入的參數SIZE。當一個線程調用await方法的時候會掛起,直到該對象收到SIZE次countDown。一個對象只能使用一次。

CyclicBarrier也是有一個SIZE參數。當有SIZE個線程調用await的時候,全部線程都會被喚醒。可以理解為所有運動員就位后才能起跑,早就位的運動員只能掛起等待。它可以重復利用。

DelayQueue一個無界的BlockingQueue,用來放置實現了Delay接口的對象,在隊列中的對象只有在到期之后才能被取走。如果沒有任何對象到期,就沒有頭元素。

PriorityBlockingQueue一種自帶優(yōu)先級的阻塞式隊列。

ScheduledExecutor可以把它想象成一種線程池式的Timer, TimerTask。

Semaphore互斥鎖只允許一個線程訪問資源,但是Semaphore允許SIZE個線程同時訪問資源。

Exchanger生產者消費者問題的特殊版。兩個線程可以在都‘準備好了’之后交換一個對象的控制權。

ReadWriteLock讀寫鎖。 讀-讀不互斥,讀-寫互斥,寫-寫互斥。

文/于曉飛93原文:http://www.jianshu.com/p/cb1a23bc82d0
標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
www成人在线视频| 美女高潮久久久| av综合电影网站| 亚洲永久av| 精品久久久网| av在线资源| 99视频精品全国免费| 99成人在线视频| 婷婷成人基地| 中文在线一区| 日本天堂一区| 久久香蕉网站| 日韩av有码| 欧美日一区二区| 国产一级久久| 天堂va在线高清一区| 69精品国产久热在线观看| 国产乱码精品一区二区三区四区| 国产精品毛片视频| 麻豆国产欧美一区二区三区| 岛国av免费在线观看| 亚洲天堂1区| 国产精品普通话对白| 亚洲精品国产精品粉嫩| 欧美亚洲色图校园春色| 成人台湾亚洲精品一区二区| 欧美日韩亚洲在线观看| 综合激情在线| 久久字幕精品一区| 精品在线99| 五月亚洲婷婷 | 国产精品毛片在线看| 在线一区二区三区视频| 国产亚洲精品美女久久| 国产成人精品一区二区三区视频| 久久中文字幕av一区二区不卡| 美女被久久久| 欧美1区二区| 激情欧美日韩一区| 日韩av一区二| 国产欧美一区二区三区精品酒店| 欧美.日韩.国产.一区.二区 | 国产欧美激情| 999精品一区| 日本欧美大码aⅴ在线播放| 国产69精品久久| 蜜桃视频免费观看一区| 国语精品一区| 视频一区欧美日韩| 色欧美自拍视频| 免费在线看一区| 麻豆一区二区三| 黄色av一区| 精品国产一区二区三区av片| 99久久精品国产亚洲精品| 日本一区免费网站| 久久精品中文| 国产亚洲精品美女久久| 久久要要av| 国产伦乱精品| 亚洲免费中文| www.九色在线| 日韩精品五月天| 99成人在线视频| 国产精品免费大片| 国产免费成人| 国产96在线亚洲| 日韩一区精品| 亚洲二区精品| 国产精品网在线观看| 国产视频亚洲| 国产美女高潮在线| 国产欧美日韩一级| 亚洲在线电影| 成人久久久久| 久久只有精品| 日本不卡视频在线| 最新日韩av| 日韩中文在线电影| 国产精品视频一区二区三区四蜜臂 | 蜜臀久久99精品久久久久宅男| 国内揄拍国内精品久久| 中文字幕av亚洲精品一部二部 | 蜜桃视频在线观看一区| 日韩欧美一区二区三区免费观看| 国产精品丝袜在线播放| 在线一区二区三区视频| 色爱综合av| 精品视频国内| 欧美综合社区国产| 在线精品一区二区| 伊人久久亚洲美女图片| 黄色aa久久| 久久久国产精品入口麻豆| 日本aⅴ亚洲精品中文乱码| 午夜在线一区二区| 激情综合网址| 色一区二区三区| 久久精品国产99国产精品| 国产无遮挡裸体免费久久| 免费视频一区二区| 黄色成人91| 三级精品视频| 国产精品成人一区二区不卡| 免费亚洲一区| 国产精品久久久久久久久免费高清| 在线观看亚洲精品福利片| 99视频在线精品国自产拍免费观看| 久久久精品五月天| 成人福利视频| 日韩国产欧美| 精品国产免费人成网站| 精品一区二区三区亚洲| 国产精品成人一区二区网站软件| 日本午夜精品久久久| 人人精品久久| 国产亚洲一区| 国产欧美日韩精品一区二区免费 | 亚洲欧美日韩国产一区二区| 欧美日韩激情| 亚洲精品电影| 亚洲精品1区| 蜜桃久久av| 亚洲人亚洲人色久| 亚洲精选久久| 日本欧美韩国一区三区| 日韩激情啪啪| 午夜精品福利影院| 91精品丝袜国产高跟在线| 午夜电影一区| 日韩av午夜在线观看| 国产亚洲高清一区| 久久精品网址| 成人台湾亚洲精品一区二区 | 亚洲伦乱视频| 亚洲特色特黄| 国产婷婷精品| 亚洲深夜福利在线观看| 日韩激情综合| 欧美aaaaaa午夜精品| 精品国产一区二| 香蕉成人av| 久久麻豆精品| 久久夜色精品| 国产精品亚洲综合色区韩国| 久久这里只有| 99久久精品网| 亚洲一区二区三区久久久| 日韩福利在线观看| 精品中文在线| 久久精品动漫| 另类av一区二区| 国产探花一区| 亚洲一级少妇| 亚洲色图网站| 老司机精品视频在线播放| 在线亚洲人成| 欧美日韩视频| 欧美片第1页综合| av免费不卡国产观看| 99在线精品视频在线观看| 日本成人中文字幕| 精品99久久| 亚洲资源av| 国产高清日韩| 久久伦理在线| 日韩精品欧美大片| 极品av在线| 丝袜亚洲另类欧美| 国产精品videossex久久发布| 日韩国产在线| 亚洲精品一级| 日本精品黄色| 日韩中文字幕亚洲一区二区va在线| 国产精品亚洲综合色区韩国| 日韩中文影院| 日韩高清成人在线| 中文一区一区三区高中清不卡免费| 国产精品毛片在线| 精品国产一区二区三区性色av| 亚洲手机在线| 国产欧美三级| 免费观看不卡av| 国产欧美自拍一区| 久久一级电影| 欧美精品福利| 亚洲精品一区二区妖精| 日韩国产欧美视频| 日本少妇一区| 欧美亚洲色图校园春色| 久久一区二区三区喷水| 国产另类在线| 久久大逼视频| 女生影院久久| 国产欧美日韩精品一区二区免费 | 日韩在线免费| 欧美亚洲二区| av亚洲免费| 久久精品一区二区国产| 免费在线观看视频一区|