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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

多线程之深入浅出

發(fā)布時(shí)間:2024/3/13 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多线程之深入浅出 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

為什么要使用多線程

網(wǎng)站的訪問(wèn)量非常的巨大,常常會(huì)出現(xiàn)多個(gè)用戶端訪問(wèn)客戶端的情況,多線程可以使我們更好去應(yīng)對(duì)這種高并發(fā)的情況,最大可能去充分利用cpu,加快訪問(wèn)速度,提升用戶使用的舒適度

分清進(jìn)程線程

進(jìn)程:
1. 進(jìn)程是程序的一次動(dòng)態(tài)執(zhí)行過(guò)程, 占用特定的地址空間。
2. 每個(gè)進(jìn)程由3部分組成:cpu、data、code。每個(gè)進(jìn)程都是獨(dú)立的,保有自己的cpu時(shí)間,代碼和數(shù)據(jù),即便用同一份程序產(chǎn)生好幾個(gè)進(jìn)程,它們之間還是擁有自己的這3樣?xùn)|西,這樣的缺點(diǎn)是:浪費(fèi)內(nèi)存,cpu的負(fù)擔(dān)較重。
3. 多任務(wù)(Multitasking)操作系統(tǒng)將CPU時(shí)間動(dòng)態(tài)地劃分給每個(gè)進(jìn)程,操作系統(tǒng)同時(shí)執(zhí)行多個(gè)進(jìn)程,每個(gè)進(jìn)程獨(dú)立運(yùn)行。以進(jìn)程的觀點(diǎn)來(lái)看,它會(huì)以為自己獨(dú)占CPU的使用權(quán)。
4. 進(jìn)程的查看
Windows系統(tǒng): Ctrl+Alt+Del,啟動(dòng)任務(wù)管理器即可查看所有進(jìn)程。
Unix系統(tǒng): ps or top。

線程:
一個(gè)進(jìn)程可以產(chǎn)生多個(gè)線程。同多個(gè)進(jìn)程可以共享操作系統(tǒng)的某些資源一樣,同一進(jìn)程的多個(gè)線程也可以共享此進(jìn)程的某些資源(比如:代碼、數(shù)據(jù)),所以線程又被稱(chēng)為輕量級(jí)進(jìn)程(lightweight process)。
1. 一個(gè)進(jìn)程內(nèi)部的一個(gè)執(zhí)行單元,它是程序中的一個(gè)單一的順序控制流程。
2. 一個(gè)進(jìn)程可擁有多個(gè)并行的(concurrent)線程。
3. 一個(gè)進(jìn)程中的多個(gè)線程共享相同的內(nèi)存單元/內(nèi)存地址空間,可以訪問(wèn)相同的變量和對(duì)象,而且它們從同一堆中分配對(duì)象并進(jìn)行通信、數(shù)據(jù)交換和同步操作。
4. 由于線程間的通信是在同一地址空間上進(jìn)行的,所以不需要額外的通信機(jī)制,這就使得通信更簡(jiǎn)便而且信息傳遞的速度也更快。
5. 線程的啟動(dòng)、中斷、消亡,消耗的資源非常少。

線程和進(jìn)程的區(qū)別:
1. 每個(gè)進(jìn)程都有獨(dú)立的代碼和數(shù)據(jù)空間(進(jìn)程上下文),進(jìn)程間的切換會(huì)有較大的開(kāi)銷(xiāo)
2. 線程可以看成是輕量級(jí)的進(jìn)程,屬于同一進(jìn)程的線程共享代碼和數(shù)據(jù)空間,每個(gè)線程有獨(dú)立的運(yùn)行棧和程序計(jì)數(shù)器(PC),線程切換的開(kāi)銷(xiāo)小。
3. 線程和進(jìn)程最根本的區(qū)別在于:進(jìn)程是資源分配的單位,線程是調(diào)度和執(zhí)行的單位。
4. 多進(jìn)程: 在操作系統(tǒng)中能同時(shí)運(yùn)行多個(gè)任務(wù)(程序)。
5. 多線程: 在同一應(yīng)用程序中有多個(gè)順序流同時(shí)執(zhí)行。
6. 線程是進(jìn)程的一部分,所以線程有的時(shí)候被稱(chēng)為輕量級(jí)進(jìn)程。
7. . 一個(gè)沒(méi)有線程的進(jìn)程是可以被看作單線程的,如果一個(gè)進(jìn)程內(nèi)擁有多個(gè)線程,進(jìn)程的執(zhí)行過(guò)程不是一條線(線程)的,而是多條線(線程)共同完成的。
8. 系統(tǒng)在運(yùn)行的時(shí)候會(huì)為每個(gè)進(jìn)程分配不同的內(nèi)存區(qū)域,但是不會(huì)為線程分配內(nèi)存(線程所使用的資源是它所屬的進(jìn)程的資源),線程組只能共享資源。那就是說(shuō),除了CPU之外(線程在運(yùn)行的時(shí)候要占用CPU資源),計(jì)算機(jī)內(nèi)部的軟硬件資源的分配與線程無(wú)關(guān),線程只能共享它所屬進(jìn)程的資源。
進(jìn)程與程序的區(qū)別:
程序是一組指令的集合,它是靜態(tài)的實(shí)體,沒(méi)有執(zhí)行的含義。而進(jìn)程是一個(gè)動(dòng)態(tài)的實(shí)體,有自己的生命周期。一般說(shuō)來(lái),一個(gè)進(jìn)程肯定與一個(gè)程序相對(duì)應(yīng),并且只有一個(gè),但是一個(gè)程序可以有多個(gè)進(jìn)程,或者一個(gè)進(jìn)程都沒(méi)有。除此之外,進(jìn)程還有并發(fā)性和交往性。簡(jiǎn)單地說(shuō),進(jìn)程是程序的一部分,程序運(yùn)行的時(shí)候會(huì)產(chǎn)生進(jìn)程。

創(chuàng)建多線程的四大方式

一.繼承Thread類(lèi)(這種不推薦,類(lèi)單繼承,后期不易于代碼維護(hù))

/*** 創(chuàng)建線程的方式一:* 創(chuàng)建:繼承Thread+重寫(xiě)run方法* 啟動(dòng):.start()* 不推薦,因?yàn)閖ava中類(lèi)單繼承,不易于后期代碼維護(hù)* @author Zrd*/ public class StartThread extends Thread{/*** run方法是線程入口點(diǎn)*/@Overridepublic void run () {for(int i=0;i<20;i++){System.out.println("聽(tīng)歌");}}public static void main(String[] args){new StartThread().start();for(int i=0;i<100;i++){System.out.println("敲代碼");}} }

二.實(shí)現(xiàn)Runnable接口(推薦,避免單繼承的局限性)

/*** 創(chuàng)建線程的方式二:* 創(chuàng)建:實(shí)現(xiàn)Runnable+重寫(xiě)run* 啟動(dòng):創(chuàng)建實(shí)現(xiàn)類(lèi)對(duì)象+Thread對(duì)象+start* 推薦:避免了單繼承的局限性,優(yōu)先使用接口,便于后期代碼維護(hù)* 方便資源共享* @author Zrd*/ public class StartRunnable implements Runnable{/*** run方法不能拋出異常,只能try catch*/@Overridepublic void run () {for(int i=0;i<20;i++){System.out.println("聽(tīng)歌");}}public static void main (String[] args) {//創(chuàng)建代理對(duì)象new Thread(new StartRunnable()).start();for(int i=0;i<100;i++){System.out.println("敲代碼");}} }

三.實(shí)現(xiàn)Callable接口(推薦,juc中使用,屬于高級(jí)并發(fā)編程,筆者暫時(shí)能力有限,先臨摹,等深入了解后再來(lái)做分析)

/*** 創(chuàng)建線程的方式三:* Callable+重寫(xiě)run;創(chuàng)建執(zhí)行服務(wù);提交執(zhí)行;獲取結(jié)果;關(guān)閉服務(wù)* 高級(jí)并發(fā)編程中使用* @author Zrd*/ public class StartCallable implements Callable<Boolean> {@Overridepublic Boolean call () throws Exception {for(int i=0;i<20;i++){System.out.println("聽(tīng)歌"+i);}return true;}public static void main (String[] args) throws Exception{StartCallable c1 = new StartCallable();StartCallable c2 = new StartCallable();StartCallable c3 = new StartCallable();//創(chuàng)建執(zhí)行服務(wù)ExecutorService executorService = Executors.newFixedThreadPool(3);//提交執(zhí)行Future< Boolean > s1 = executorService.submit(c1);Future< Boolean > s2 = executorService.submit(c2);Future< Boolean > s3 = executorService.submit(c3);//獲取結(jié)果s1.get();s2.get();s3.get();//關(guān)閉服務(wù)executorService.shutdownNow();} }

四:線程池(筆者暫時(shí)還未涉略,后期深入理解后再做補(bǔ)充)

線程狀態(tài)

一個(gè)線程對(duì)象在它的生命周期內(nèi),需要經(jīng)歷5個(gè)狀態(tài):

操控線程狀態(tài)的幾種方式:
一.sleep(睡眠)
使用sleep,讓正在運(yùn)行的線程進(jìn)入阻塞狀態(tài),直到休眠時(shí)間滿了,進(jìn)入就緒狀態(tài)。(不會(huì)釋放鎖)

public class TestThreadState {public static void main(String[] args) {StateThread thread1 = new StateThread();thread1.start();StateThread thread2 = new StateThread();thread2.start();} } //使用繼承方式實(shí)現(xiàn)多線程 class StateThread extends Thread {public void run() {for (int i = 0; i < 100; i++) {System.out.println(this.getName() + ":" + i);try {Thread.sleep(2000);//調(diào)用線程的sleep()方法;} catch (InterruptedException e) {e.printStackTrace();}}} }

二:yield (禮讓)
使用yield,讓正在運(yùn)行的線程直接進(jìn)入就緒狀態(tài),讓出CPU的使用權(quán)。(線程重新競(jìng)爭(zhēng)cpu的使用權(quán),所以禮讓不一定成功

public class TestThreadState {public static void main(String[] args) {StateThread thread1 = new StateThread();thread1.start();StateThread thread2 = new StateThread();thread2.start();} } //使用繼承方式實(shí)現(xiàn)多線程 class StateThread extends Thread {public void run() {for (int i = 0; i < 100; i++) {System.out.println(this.getName() + ":" + i);Thread.yield();//調(diào)用線程的yield()方法;}} }

三.線程的聯(lián)合join()
線程A在運(yùn)行期間,可以調(diào)用線程B的join()方法,讓線程B和線程A聯(lián)合。這樣,線程A就必須等待線程B執(zhí)行完畢后,才能繼續(xù)執(zhí)行。如下面示例中,“爸爸線程”要抽煙,于是聯(lián)合了“兒子線程”去買(mǎi)煙,必須等待“兒子線程”買(mǎi)煙完畢,“爸爸線程”才能繼續(xù)抽煙。

public class TestThreadState {public static void main(String[] args) {System.out.println("爸爸和兒子買(mǎi)煙故事");Thread father = new Thread(new FatherThread());father.start();} }class FatherThread implements Runnable {public void run() {System.out.println("爸爸想抽煙,發(fā)現(xiàn)煙抽完了");System.out.println("爸爸讓兒子去買(mǎi)包紅塔山");Thread son = new Thread(new SonThread());son.start();System.out.println("爸爸等兒子買(mǎi)煙回來(lái)");try {son.join();} catch (InterruptedException e) {e.printStackTrace();System.out.println("爸爸出門(mén)去找兒子跑哪去了");// 結(jié)束JVM。如果是0則表示正常結(jié)束;如果是非0則表示非正常結(jié)束System.exit(1);}System.out.println("爸爸高興的接過(guò)煙開(kāi)始抽,并把零錢(qián)給了兒子");} }class SonThread implements Runnable {public void run() {System.out.println("兒子出門(mén)去買(mǎi)煙");System.out.println("兒子買(mǎi)煙需要10分鐘");try {for (int i = 1; i <= 10; i++) {System.out.println("第" + i + "分鐘");Thread.sleep(1000);}} catch (InterruptedException e) {e.printStackTrace();}System.out.println("兒子買(mǎi)煙回來(lái)了");} }

獲取線程基本信息的方法


線程的常用方法一

public class TestThread {public static void main(String[] argc) throws Exception {Runnable r = new MyThread();Thread t = new Thread(r, "Name test");//定義線程對(duì)象,并傳入?yún)?shù);t.start();//啟動(dòng)線程;System.out.println("name is: " + t.getName());//輸出線程名稱(chēng);Thread.currentThread().sleep(5000);//線程暫停5分鐘;System.out.println(t.isAlive());//判斷線程還在運(yùn)行嗎?System.out.println("over!");} } class MyThread implements Runnable {//線程體;public void run() {for (int i = 0; i < 10; i++)System.out.println(i);} }

線程的優(yōu)先級(jí)

一.處于就緒狀態(tài)的線程,會(huì)進(jìn)入“就緒隊(duì)列”等待JVM來(lái)挑選。
二.線程的優(yōu)先級(jí)用數(shù)字表示,范圍從1到10,一個(gè)線程的缺省優(yōu)先級(jí)是5。
三.使用下列方法獲得或設(shè)置線程對(duì)象的優(yōu)先級(jí)
int getPriority();
void setPriority(int newPriority);
注意:優(yōu)先級(jí)低只是意味著獲得調(diào)度的概率低。并不是絕對(duì)先調(diào)用優(yōu)先級(jí)高的線程后調(diào)用優(yōu)先級(jí)低的線程。

public class TestThread {public static void main(String[] args) {Thread t1 = new Thread(new MyThread(), "t1");Thread t2 = new Thread(new MyThread(), "t2");t1.setPriority(1);t2.setPriority(10);t1.start();t2.start();} } class MyThread extends Thread {public void run() {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + ": " + i);}} }

線程同步

一.什么是線程同步?
線程同步的本質(zhì)是一種等待機(jī)制,在處理多線程問(wèn)題中,多個(gè)線程同時(shí)訪問(wèn)一個(gè)對(duì)象,有些甚至想修改這個(gè)對(duì)象,假如我們不做人很處理,就會(huì)出現(xiàn)數(shù)據(jù)不正確(線程不安全)的問(wèn)題,解決思路:多個(gè)需要同時(shí)訪問(wèn)這個(gè)對(duì)象的線程進(jìn)入這個(gè)對(duì)象的等待池形成隊(duì)列,等前面的線程處理完畢后,下一個(gè)線程再使用

二. 實(shí)現(xiàn)線程同步
使用synchronized關(guān)鍵字;它包括兩種用法:synchronized 方法synchronized 塊
1.synchronized 方法
通過(guò)在方法聲明中加入 synchronized關(guān)鍵字來(lái)聲明,語(yǔ)法如下:

public synchronized void accessVal(int newVal);

synchronized 方法控制對(duì)“對(duì)象的類(lèi)成員變量”的訪問(wèn):每個(gè)對(duì)象對(duì)應(yīng)一把鎖,每個(gè) synchronized 方法都必須獲得調(diào)用該方法的對(duì)象的鎖方能執(zhí)行,否則所屬線程阻塞,方法一旦執(zhí)行,就獨(dú)占該鎖,直到從該方法返回時(shí)才將鎖釋放,此后被阻塞的線程方能獲得該鎖,重新進(jìn)入可執(zhí)行狀態(tài)。
缺陷:若將一個(gè)大的方法聲明為synchronized 將會(huì)大大影響效率。
2.synchronized塊
相比起synchronized 方法的優(yōu)勢(shì):精確地控制到具體的“成員變量”,縮小同步的范圍,提高效率。

synchronized(syncObject){ //允許訪問(wèn)控制的代碼 }

自定義一個(gè)類(lèi)測(cè)試synchronized 方法,代碼如下

/*** 線程安全:在并發(fā)的時(shí)候保證數(shù)據(jù)的正確性,效率盡可能的高* 1。采用synchronized 同步方法 (鎖的是this)* @author Zrd*/ public class SynchronizeTest01 {public static void main (String[] args) {SafeWeb12306 safeWeb12306 = new SafeWeb12306();new Thread(safeWeb12306,"線程一").start();new Thread(safeWeb12306,"線程二").start();} }/*** 定義一個(gè)搶票類(lèi),體會(huì)同步方法*/ class SafeWeb12306 implements Runnable{/*** 票數(shù)*/private int votes=10;/*** 標(biāo)識(shí) 判斷是否還有票*/private boolean flag=true;@Overridepublic void run () {while (flag){test();}}public synchronized void test(){/*** 當(dāng)票數(shù)<=0 時(shí)候 直接跳出方法*/if(votes<=0){flag=false;return;}//模擬延時(shí)try {Thread.sleep(200);}catch (InterruptedException e){//阻塞異常e.printStackTrace();}System.out.println(Thread.currentThread().getName()+votes--);} }

自定義一個(gè)synchronized塊案例,代碼如下:

/*** 線程安全* 2.采用synchronized(obj){} 同步塊直接鎖資源,提高性能* @author Zrd*/ public class SynchronizeTest02 {public static void main (String[] args) {Account account = new Account(150, "總賬戶");Withdrawal w1 = new Withdrawal(account, "一號(hào)操作員", 30);Withdrawal w2 = new Withdrawal(account, "二號(hào)操作員", 30);Withdrawal w3 = new Withdrawal(account, "三號(hào)操作員", 90);Withdrawal w4 = new Withdrawal(account, "四號(hào)操作員", 90);new Thread(w1).start();new Thread(w2).start();new Thread(w3).start();new Thread(w4).start();} } /*** 存款賬戶類(lèi)*/ class Account{/*** 余額*/int balance;/*** 賬戶姓名*/String accountName;public Account () {}public Account (int balance, String accountName) {this.balance = balance;this.accountName = accountName;} } /*** 模擬取款類(lèi)*/ class Withdrawal implements Runnable{/*** 賬戶對(duì)象*/private Account account;/*** 操作員*/private String operator;/*** 取走的金額*/private int fundsWithdrawn;public Withdrawal (Account account, String operator, int fundsWithdrawn) {this.account = account;this.operator = operator;this.fundsWithdrawn = fundsWithdrawn;}public Withdrawal () {}/*** 使用synchronized塊鎖賬戶資源 account*/@Overridepublic void run () {//采取優(yōu)化,當(dāng)余額<0直接跳出方法, 不需要去鎖資源 ,提高性能if(account.balance-fundsWithdrawn<0){return;}/*** 注意synchronized只能鎖住一個(gè)對(duì)象* 當(dāng)需要同時(shí)鎖多個(gè)對(duì)象,將對(duì)象進(jìn)行包裝,鎖住包裝類(lèi)*/synchronized (account){if(account.balance-fundsWithdrawn<0){return;}else {System.out.println(operator+"取走了"+account.accountName+" "+fundsWithdrawn+"元,剩下"+(account.balance-fundsWithdrawn));//總賬戶的錢(qián)減去取走的錢(qián)account.balance=account.balance-fundsWithdrawn;}}} }

死鎖的出現(xiàn)和解決方案

一.什么時(shí)候會(huì)出現(xiàn)死鎖
多個(gè)線程各自占有一些共享資源,并且互相等待其他線程占有的資源才能進(jìn)行,而導(dǎo)致兩個(gè)或者多個(gè)線程都在等待對(duì)方釋放資源,都停止執(zhí)行的情形。
某一個(gè)同步塊需要同時(shí)擁有“兩個(gè)以上對(duì)象的鎖”時(shí),就可能會(huì)發(fā)生“死鎖”的問(wèn)題

死鎖的解決方案
出現(xiàn)死鎖一般是鎖中嵌套鎖,解決的方案是:將鎖從另外一個(gè)鎖中解套出來(lái)

下面編寫(xiě)一個(gè)案例體會(huì)死鎖的出現(xiàn),和解決方案

/*** 死鎖:過(guò)多的同步可能造成相互不釋放資源* 從而相互等待,一般發(fā)生與同步塊中持有多個(gè)對(duì)象的鎖* 解決方案:不要在鎖中嵌套鎖,解套* @author Zrd*/ public class DeadLock {public static void main (String[] args) {for(int i=0;i<100;i++){MakeUp g1 = new MakeUp(true, "一號(hào)女孩");MakeUp g2 = new MakeUp(false, "二號(hào)女孩");new Thread(g1).start();new Thread(g2).start();}} }/*** 口紅類(lèi)*/ class Lipstick{}/*** 鏡子類(lèi)*/ class Mirror{} /*** 化妝*/ class MakeUp implements Runnable{/*** 口紅對(duì)象,采用static 保證只有一只口紅* 對(duì)static對(duì)象初始化*/static Lipstick lipstick=new Lipstick();/*** 鏡子對(duì)象,采用static 保證只有一面鏡子*/static Mirror mirror=new Mirror();/*** true->選擇口紅,false->選擇鏡子*/boolean choice;/*** 化妝女孩對(duì)象*/String girl;public MakeUp () {}public MakeUp (boolean choice, String girl) {this.choice = choice;this.girl = girl;}/***包含兩個(gè)案例一個(gè)會(huì)出現(xiàn)死鎖,一個(gè)是基于對(duì)死鎖的解決*/@Overridepublic void run () {/*** 死鎖案例*/try {makeUpDeadLock();} catch (InterruptedException e) {e.printStackTrace();}/*** 解決后的案例*/try {makeUpDeadLockSolved();} catch (InterruptedException e) {e.printStackTrace();}}/*** 死鎖案例* 化妝過(guò)程 鎖中嵌套了鎖,容易出現(xiàn)死鎖*/private void makeUpDeadLock() throws InterruptedException {if (choice){//獲得口紅鎖synchronized (lipstick){System.out.println(this.girl+"獲得口紅");//1秒后 ,獲取鏡子Thread.sleep(1000);//獲得鏡子鎖synchronized (mirror){System.out.println(this.girl+"獲得鏡子");}}}else {//獲得鏡子鎖synchronized (mirror){System.out.println(this.girl+"獲得鏡子");//1秒后 ,獲取口紅Thread.sleep(1200);//獲得口紅鎖synchronized (lipstick){System.out.println(this.girl+"獲得口紅");}}}}/*** 解決死鎖案例* 思路,解套*/private void makeUpDeadLockSolved() throws InterruptedException {if (choice){//獲得口紅鎖synchronized (lipstick){System.out.println(this.girl+"獲得口紅");}//1秒后 ,獲取鏡子Thread.sleep(1000);//獲得鏡子鎖synchronized (mirror){System.out.println(this.girl+"獲得鏡子");}}else {//獲得鏡子鎖synchronized (mirror){System.out.println(this.girl+"獲得鏡子");}//1秒后 ,獲取口紅Thread.sleep(1000);//獲得口紅鎖synchronized (lipstick){System.out.println(this.girl+"獲得口紅");}}} }

解決并發(fā)的幾種模式(筆者還沒(méi)開(kāi)始學(xué)juc 暫時(shí)寫(xiě)一種 后續(xù)學(xué)到了再做補(bǔ)充)

一 生產(chǎn)者于消費(fèi)者模式
兩種方式實(shí)現(xiàn)
1.管程法:通過(guò)定義一個(gè)緩沖容器判斷緩沖容器中空間存放情況,有空間生產(chǎn)者就生產(chǎn)數(shù)據(jù),有數(shù)據(jù)消費(fèi)者就可以進(jìn)行消費(fèi),不能的話就線程等待Thread.wait(),生產(chǎn)和消費(fèi)之間可以相互通知Thread.notiflyAll()
下面編寫(xiě)一個(gè)案例體會(huì)管程法:

package 多線程.并發(fā).幾種解決并發(fā)的模式;/*** 生產(chǎn)者與消費(fèi)者實(shí)現(xiàn)方式一:管程法* 解決的問(wèn)題:1.什么時(shí)候能生產(chǎn),2什么時(shí)候能消費(fèi)* 借助緩沖容器* @author Zrd*/ public class ManagementMethod {public static void main (String[] args) {BufferContainer bufferContainer = new BufferContainer();new Thread(new Producer(bufferContainer)).start();new Thread(new Consumer(bufferContainer)).start();} }/*** 生產(chǎn)者*/ class Producer implements Runnable{BufferContainer bufferContainer;public Producer (BufferContainer bufferContainer) {this.bufferContainer = bufferContainer;}@Overridepublic void run () {//生產(chǎn)數(shù)據(jù)for(int i=0;i<100;i++){bufferContainer.push(new Data(i));System.out.println("生產(chǎn)了"+i+"數(shù)據(jù)");}} }/*** 消費(fèi)者*/ class Consumer implements Runnable{BufferContainer bufferContainer;public Consumer (BufferContainer bufferContainer) {this.bufferContainer = bufferContainer;}@Overridepublic void run () {//消費(fèi)數(shù)據(jù)for(int i=0;i<20;i++){bufferContainer.pop();System.out.println("消費(fèi)了"+i+"數(shù)據(jù)");}} }/*** 數(shù)據(jù)緩沖區(qū)* 本質(zhì)上是定義一個(gè)緩沖容器*/ class BufferContainer{/*** 定義一個(gè)大小為10的Data數(shù)組,用作數(shù)據(jù)緩存容器*/Data[] datas=new Data[10];/*** 計(jì)數(shù)器*/int count=0;/*** 存數(shù)據(jù)*/public synchronized void push(Data data) {/*** 什么時(shí)候能生產(chǎn)數(shù)據(jù),容器中存在空間* 當(dāng)容器中不存在空間,只能等待*/if(count==datas.length){//this.wait() 當(dāng)前線程處于阻塞狀態(tài),等待消費(fèi)者的通知try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}//容器有空間可以消費(fèi)datas[count]=data;count++;//通知消費(fèi)者消費(fèi)this.notifyAll();}/***獲取數(shù)據(jù)*/public synchronized Data pop() {/*** 何時(shí)能消費(fèi)?* 判斷容器中是否存在數(shù)據(jù)* 容器中沒(méi)有數(shù)據(jù),只能等待*/if(count==0){//this.wait() 當(dāng)前線程處于阻塞狀態(tài),等待生產(chǎn)者的通知try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}//存在數(shù)據(jù)可以消費(fèi)count--;//通知生產(chǎn)者生產(chǎn)this.notifyAll();return datas[count];}} /*** 數(shù)據(jù)*/ class Data{/*** 加入一個(gè)成員 好區(qū)別*/int i;public Data (int i) {this.i = i;}public Data () {} }

2.信號(hào)燈法:通過(guò)定義一個(gè)標(biāo)識(shí)位*,控制生產(chǎn)和消費(fèi)的實(shí)現(xiàn)
下面編寫(xiě)一個(gè)案例體會(huì)信號(hào)燈法:

package 多線程.并發(fā).幾種解決并發(fā)的模式;import java.lang.reflect.TypeVariable;/*** 生產(chǎn)者與消費(fèi)者實(shí)現(xiàn)方式二:信號(hào)燈法* 解決的問(wèn)題:1.什么時(shí)候能生產(chǎn),2什么時(shí)候能消費(fèi)* 借助標(biāo)識(shí)位* @author Zrd*/ public class SemaphoreMethod {public static void main (String[] args) {Tv tv = new Tv();new Thread(new Actor(tv)).start();new Thread(new Audience(tv)).start();} }/*** 電視類(lèi)* 演員表演 和 觀眾觀看*/ class Tv{/*** 選擇做的事情*/String voice;/*** true->演員表演,false->觀眾觀看*/boolean flag;/*** 演員表演(生產(chǎn))*/public synchronized void play(){/*** 借助標(biāo)識(shí)位,控制能否表演* 等待*/if(!flag){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}//開(kāi)始表演(生產(chǎn))System.out.println(this.voice);//改變標(biāo)識(shí)位flag=false;//通知觀看(消費(fèi)) 喚醒等待的線程this.notifyAll();}/*** 觀眾觀看(消費(fèi))*/public synchronized void watch(){/*** 借助標(biāo)識(shí)位,控制能否觀看* 等待*/if(flag){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}//開(kāi)始觀看(消費(fèi))System.out.println(this.voice);//改變標(biāo)識(shí)位flag=true;//通知生產(chǎn)(生產(chǎn)) 喚醒等待的線程this.notifyAll();} } class Actor implements Runnable{/*** 操作tv對(duì)象*/Tv tv;public Actor (Tv tv) {this.tv = tv;}@Overridepublic void run () {for(int i=0;i<100;i++){tv.voice="生產(chǎn)(演員)"+i;tv.play();}} } class Audience implements Runnable{/*** 操作tv對(duì)象*/Tv tv;public Audience (Tv tv) {this.tv = tv;}@Overridepublic void run () {for(int i=0;i<20;i++){tv.voice="消費(fèi)(觀眾)"+i;tv.watch();}} }

總結(jié)

以上是生活随笔為你收集整理的多线程之深入浅出的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产精品99一区二区三区 | 久久高清内射无套 | 91中出 | 国产主播专区 | 69av在线视频| 青娱乐国产在线视频 | 尤物视频在线观看国产性感 | 国产乡下妇女做爰 | 91久久精品日日躁夜夜躁欧美 | 国产午夜在线观看 | 美女露胸无遮挡 | 毛片一级视频 | 国产午夜精品一区二区三区 | 欧美精品久久久久 | 色优久久 | 日韩精品一区二区三区不卡在线 | 黄色免费在线观看网站 | 91在线视频观看 | 国产福利免费在线观看 | 性高潮在线观看 | 亚州黄色 | 欧美视频一区二区三区四区在线观看 | 成年人免费网站在线观看 | 秋霞啪啪片 | av手机天堂 | 久久久天天 | 久久久老熟女一区二区三区91 | 波多野结衣在线观看一区二区三区 | 天天影视亚洲 | 欧美 日韩 成人 | 高清一区二区三区四区五区 | 国产精品久久久久影院老司 | 精品亚洲中文字幕 | 亚洲人女屁股眼交6 | 欧美www视频 | 大肉大捧一进一出好爽mba | 欧美精品hd | 欧美大片免费观看 | 日韩一区网站 | 国产精品无码专区 | 人人爱爱 | 香蕉视频久久久 | 射进来av影视 | 亚洲综合色小说 | 成人免费久久 | 中国少妇色 | 久久第一页 | 在线精品视频一区 | 欧美一区二区视频在线观看 | 在线观看免费视频一区二区 | 青青草原国产视频 | 第一页综合 | 一区一区三区产品乱码 | 成人亚洲一区二区 | 精品人人| 九九精品久久 | 亚洲精品123区 | 日韩三级精品 | 美女毛片视频 | 中文字幕码精品视频网站 | 肉性天堂 | 老熟妇一区二区三区 | 捆绑无遮挡打光屁股 | 一本色道久久综合亚洲精品 | 中出在线 | 久久久久亚洲AV成人无码国产 | 91大神精品在线 | av中文在线资源 | 亚洲色图第三页 | 69国产精品视频免费观看 | av电影一区二区 | 亚洲午夜无码av毛片久久 | 亚洲理论视频 | 天堂av中文在线观看 | 中国少妇色 | 日本人妻换人妻毛片 | 青娱乐在线免费视频 | 精品国产xxx| 国产精品无码AV | 91美女视频在线观看 | 在线视频污| 91人人爱| 亚洲第一页视频 | 成人羞羞在线观看网站 | 99re视频| 日韩在线视频播放 | 国产激情一区二区三区四区 | 精品人妻一区二区三区蜜桃 | 女性向av免费网站 | 日本一区二区三区免费看 | 国产av电影一区二区三区 | 伊人久久一区二区 | 久草手机在线观看 | 一级免费黄色大片 | 美女av在线免费观看 | 亚洲精品h | 青青国产在线视频 | 少女国产免费观看 | 特黄aaaaaaaaa真人毛片 |