国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Jadual Kandungan
1 Multi-threading
1.2 Benang
1.3 Kaedah pelaksanaan multi-threading
1.3.1 Kaedah 1: Mewarisi kelas Tread
1.5 線程調(diào)度
1.6 線程控制
1.9 線程同步_同步代碼塊
1.10 線程同步_同步方法
1.11 線程安全的類(了解)
1.12 Lock鎖
1.13 線程通訊
1.14 生產(chǎn)者消費(fèi)者
1.14.1 生產(chǎn)者消費(fèi)者概述
1.14.2 生產(chǎn)者消費(fèi)者案例
Rumah Java javaTutorial Teknik klasik Java untuk mencapai penyegerakan berbilang benang dan benang

Teknik klasik Java untuk mencapai penyegerakan berbilang benang dan benang

Apr 26, 2022 pm 06:05 PM
java

Artikel ini membawakan anda pengetahuan yang berkaitan tentang java, yang terutamanya memperkenalkan isu yang berkaitan dengan penyegerakan berbilang benang dan pustaka kelas teras Mari kita lihat bersama-sama adalah membantu.

Teknik klasik Java untuk mencapai penyegerakan berbilang benang dan benang

Pembelajaran yang disyorkan: "tutorial video java"

1 Multi-threading

1.1 Proses

  • Proses : Ia adalah program berjalan
    • digunakan oleh sistem untuk sumber peruntukan dan panggilan unit Bebas
    • Setiap proses mempunyai ruang memori dan sumber sistem sendiri
  • Tiga ciri proses
    • Kebebasan: proses adalah bebas antara satu sama lain dan mempunyai kawasan ingatan bebas mereka sendiri
    • Dinamik: proses ialah program berjalan yang secara dinamik menduduki memori, CPU dan rangkaian Menunggu sumber
    • Concurrency: CPU akan meninjau dan bertukar dalam cara perkongsian masa untuk melayani setiap proses secara bergilir-gilir Kerana kelajuan pensuisan adalah sangat pantas, rasanya kami melaksanakan pada masa yang sama (concurrency: sama Terdapat berbilang pelaksanaan pada masa yang sama)

1.2 Benang

  • Benang: Ia ialah satu proses Aliran kawalan berjujukan tunggal dalam ialah laluan pelaksanaan
    • Berbenang tunggal: Proses hanya mempunyai satu laluan pelaksanaan
    • Berbilang benang: Proses mempunyai berbilang laluan pelaksanaan

1.3 Kaedah pelaksanaan multi-threading

1.3.1 Kaedah 1: Mewarisi kelas Tread

  • Proses:

    • 1 Tentukan kelas MyTread untuk mewarisi kelas Tread
    • 2 ??>3 Buat objek kelas MyTread run()
    • 4 Mulakan urutan:
    • void start()
    Mengapa kita harus mengatasi kaedah run()?
  • Kerana run() digunakan untuk merangkum kod yang dilaksanakan oleh benang

    Apakah perbezaan antara kaedah run() dan kaedah mula ()?
  • run(): merangkumkan kod yang dilaksanakan oleh thread dan memanggilnya secara terus, yang bersamaan dengan memanggil kaedah biasa

      start(): memulakan thread, dan kemudian memanggil kaedah JVM dalam thread run() ini
    Contoh
  • Kelas MyTread:
Kelas ujian
package?test;//1、定義一類MyTread繼承Tread類public?class?MyThread?extends?Thread{
????2、在MyTread類中重寫run()方法
????@Override
????public?void?run()?{
????????for(int?i=0;i
1.3.2 Kaedah 2: Laksanakan antara muka Runnable
package?test;public?class?Demo?{
????public?static?void?main(String[]?args)?{
????????//3、創(chuàng)建MyTread類的對象
????????MyThread?my1?=?new?MyThread();
????????MyThread?my2?=?new?MyThread();

????????//4、啟動(dòng)線程:void?start():啟動(dòng)線程,由Java虛擬機(jī)調(diào)用此線程的run()方法
????????my1.start();
????????my2.start();
????}}

Proses
    :
  • 1 Tentukan kelas MyRunnable untuk melaksanakan antara muka Runnable
      2 mengatasi kaedah
    • dalam kelas MyRunnable
    • 3 daripada kelas MyRunnable run()
    • 4 Cipta objek kelas Tread dan gunakan objek MyRunnable sebagai parameter pembina
    • 5
    • Faedah:
    • Elakkan Java Keterbatasan warisan tunggal
    Ia sesuai untuk situasi di mana kod berbilang atur cara yang sama memproses sumber yang sama secara berkesan memisahkan kod dan data benang dan atur cara, yang lebih mencerminkan teori reka bentuk berorientasikan objek
    • 1.3.3 Kaedah 3: Laksanakan antara muka Boleh Panggil
package?test;public?class?Demo?{
????public?static?void?main(String[]?args)?{
????????//3、創(chuàng)建MyRunnable類的對象
????????MyRunnable?mr?=?new?MyRunnable();

????????//4、創(chuàng)建Tread類的對象,把MyRunnable對象作為構(gòu)造方法的參數(shù)//????????Thread?t1?=?new?Thread(mr);//????????Thread?t2?=?new?Thread(mr);
????????//Thread(Runnable?target,String?name)
????????Thread?t1?=?new?Thread(mr,"高鐵");
????????Thread?t2?=?new?Thread(mr,"飛機(jī)");

????????//5、啟動(dòng)線程
????????t1.start();
????????t2.start();
????}}
1.4 Tetapkan dan dapatkan nama utas

Kaedah untuk menetapkan dan mendapatkan nama utas dalam kelas Thread

    • MyThread類
package?test;public?class?MyThread?extends?Thread{
????//構(gòu)造方法添加線程名稱
????public?MyThread(){}
????public?MyThread(String?name)?{
????????super(name);
????}
????
????@Override
????public?void?run()?{
????????for(int?i=0;i
  • 測試類
package?test;public?class?Demo?{
????public?static?void?main(String[]?args)?{
????????/*????????MyThread?my1?=?new?MyThread();
????????MyThread?my2?=?new?MyThread();

????????//2,void?setName(Stringname)?	將此線程的名稱更改為等于參數(shù)name
????????my1.setName("高鐵");
????????my2.setName("飛機(jī)");*/
????????
????????//3,通過構(gòu)造方法設(shè)置線程名稱
????????//需要自己定義的類中提供此帶參構(gòu)造方法,并通過super訪問父類帶參構(gòu)造方法
????????/*MyThread?my1?=?new?MyThread("高鐵");
????????MyThread?my2?=?new?MyThread("飛機(jī)");?

????????my1.start();
????????my2.start();*/
????????
????????//4,public?static?Thread?currentThread()?	返回對當(dāng)前正在執(zhí)行的線程對象的引用(可以返回main()方法中線程)
????????System.out.println(Tread.currentThread().getName());?//main
????}}

1.5 線程調(diào)度

  • 線程有兩種調(diào)度模型

    • 分時(shí)調(diào)度模型:所有線程輪流使用CPU的使用權(quán),平均分配每個(gè)線程占用CPU的時(shí)間片
    • 搶占式調(diào)度模型:優(yōu)先讓優(yōu)先級高的線程使用CPU,如果線程的優(yōu)先級相同,那么會隨機(jī)選擇一個(gè),優(yōu)先級高的線程獲取的CPU時(shí)間片相對多一些
  • Java使用的是搶占式調(diào)度模型

  • 假如計(jì)算機(jī)只有一個(gè)CPU, 那么CPU在某一個(gè)時(shí)刻只能執(zhí)行條指令, 線程只有得到CPU時(shí)間片,也就是使用權(quán),才可以執(zhí)行指令。所以說多線程程序的執(zhí)行是有隨機(jī)性,因?yàn)檎l搶到CPU的使用權(quán)是不一定的

  • Thread類中設(shè)置和獲取線程優(yōu)先級的方法

方法名 說明
public final int getPriority() [pra????r?ti] 返回此線程的優(yōu)先級
public final void setPriority(int newPriority) 更改此線程的優(yōu)先級
  • 線程默認(rèn)優(yōu)先級是5;線程優(yōu)先級范圍是:1-10
  • 線程優(yōu)先級高僅僅表示線程獲取的CPU時(shí)間的幾率高,但是要在次數(shù)比較多,或者多次運(yùn)行的時(shí)候才能看到你想要的效果
package?test;public?class?Demo?{
????public?static?void?main(String[]?args)?{

????????ThreadPriority?tp1?=?new?ThreadPriority();
????????ThreadPriority?tp2?=?new?ThreadPriority();
????????ThreadPriority?tp3?=?new?ThreadPriority();


????????tp1.setName("高鐵");
????????tp2.setName("飛機(jī)");
????????tp3.setName("汽車");

????????//1,public?final?int?getPriority()?[pra????r?ti]?	返回此線程的優(yōu)先級//????????System.out.println(tp1.getPriority());?//5//????????System.out.println(tp2.getPriority());?//5//????????System.out.println(tp3.getPriority());?//5

????????//2,public?final?void?setPriority(int?newPriority)?	更改此線程的優(yōu)先級
????????System.out.println(Thread.MAX_PRIORITY);?//10
????????System.out.println(Thread.MIN_PRIORITY);?//1
????????System.out.println(Thread.NORM_PRIORITY);?//5

????????//設(shè)置正確優(yōu)先級
????????tp1.setPriority(5);
????????tp2.setPriority(10);
????????tp3.setPriority(1);

????????tp1.start();
????????tp2.start();
????????tp3.start();
????}}

1.6 線程控制

方法名 說明
static void sleep(long millis) 使當(dāng)前正在執(zhí)行的線程停留(暫停執(zhí)行)指定的毫秒數(shù)
void join() 等待這個(gè)線程死亡
void setDaemon(boolean on) [?di?m?n] 將此線程標(biāo)記為守護(hù)線程,當(dāng)運(yùn)行的線程都是守護(hù)線程時(shí),Java虛擬機(jī)很快將退出 (并不是立刻退出)

案例:sleep()方法

  • 線程類
package?test;public?class?ThreadSleep?extends?Thread{
????@Override
????public?void?run()?{
????????for(int?i=0;i
  • 測試類
package?test;public?class?Demo?{
????public?static?void?main(String[]?args)?{

????????ThreadSleep?ts1?=?new?ThreadSleep();
????????ThreadSleep?ts2?=?new?ThreadSleep();
????????ThreadSleep?ts3?=?new?ThreadSleep();


????????ts1.setName("曹操");
????????ts2.setName("劉備");
????????ts3.setName("孫權(quán)");


????????ts1.start();
????????ts2.start();
????????ts3.start();//????????曹操:0//????????孫權(quán):0//????????劉備:0//????????孫權(quán):1//????????曹操:1//????????劉備:1//????????...
????}}

案例:join()方法

package?test;public?class?Demo?{
????public?static?void?main(String[]?args)?{

????????ThreadJoin?tj1?=?new?ThreadJoin();
????????ThreadJoin?tj2?=?new?ThreadJoin();
????????ThreadJoin?tj3?=?new?ThreadJoin();

????????tj1.setName("康熙");
????????tj2.setName("四阿哥");
????????tj3.setName("八阿哥");

????????tj1.start();
????????//2,void?join()?	等待這個(gè)線程死亡
????????try?{
????????????tj1.join();
????????}?catch?(InterruptedException?e)?{
????????????e.printStackTrace();
????????}
????????tj2.start();
????????tj3.start();//????????康熙:0//????????康熙:1//????????康熙:2//????????四阿哥:0//????????四阿哥:1//????????八阿哥:0//????????八阿哥:1//????????八阿哥:2//????????四阿哥:2//????????...
????}}

案例:setDaemon()方法

package?test;public?class?Demo?{
????public?static?void?main(String[]?args)?{

????????ThreadJoin?tj1?=?new?ThreadJoin();
????????ThreadJoin?tj2?=?new?ThreadJoin();
????????ThreadJoin?tj3?=?new?ThreadJoin();

????????tj2.setName("關(guān)羽");
????????tj3.setName("張飛");
????????//設(shè)置主線程為劉備
????????Thread.currentThread().setName("劉備");

????????//3,void?setDaemon(boolean?on)?	將此線程標(biāo)記為守護(hù)線程,當(dāng)運(yùn)行的線程都是守護(hù)線程時(shí),Java虛擬機(jī)將退出
????????tj1.setDaemon(true);
????????tj2.setDaemon(true);

????????tj1.start();
????????tj2.start();

????????for(int?i=0;i<h3><strong>1.7 線程生命周期</strong></h3><p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/331836944d1895cfc26297fee263339c-0.png" class="lazy" alt="Teknik klasik Java untuk mencapai penyegerakan berbilang benang dan benang"></p><h3><strong>1.8 數(shù)據(jù)安全問題之案例:買票</strong></h3><p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/331836944d1895cfc26297fee263339c-1.png" class="lazy" alt="Teknik klasik Java untuk mencapai penyegerakan berbilang benang dan benang"><br><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/331836944d1895cfc26297fee263339c-2.png" class="lazy" alt="Teknik klasik Java untuk mencapai penyegerakan berbilang benang dan benang"></p>
  • 為什么出現(xiàn)問題?(這也是我們判斷多線程程序是否會有數(shù)據(jù)安全問題的標(biāo)準(zhǔn))

    • 是否是多線程環(huán)境
    • 是否有共享數(shù)據(jù)
    • 是否有多條語句操作共享數(shù)據(jù)
  • 如何解決多線程安全問題呢?

  • 基本思想:讓程序沒有安全問題的環(huán)境

  • 怎么實(shí)現(xiàn)呢?

    • 把多條語句操作共享 數(shù)據(jù)的代碼給鎖起來,讓任意時(shí)刻只能有一一個(gè)線程執(zhí)行即可
    • Java提供 了同步代碼塊的方式來解決

1.9 線程同步_同步代碼塊

  • 鎖多條語句操作共享數(shù)據(jù),可以使用同步代碼塊實(shí)現(xiàn)
  • 格式
synchronized(任意對象)?{
	多條語句操作共享數(shù)據(jù)的代碼}
  • 好處:讓多個(gè)線程實(shí)現(xiàn)先后依次訪問共享資源,解決了多線程的數(shù)據(jù)安全問題

  • 弊端:當(dāng)線程很多的時(shí)候,因?yàn)槊總€(gè)線程都會去判斷同步上的鎖,這是很消耗資源的,無形中降低程序的運(yùn)行效率

  • sellTicket類

package?test;//1,定義一個(gè)類SellTicket實(shí)現(xiàn)Runnable接口,里面定義一個(gè)成員變量:?private?int?tickets=?100;public?class?SellTicket?implements?Runnable{
????private?int?tickets?=?100;
????private?Object?obj?=?new?Object();

????//2,在ellTicket類中重寫run0方法實(shí)現(xiàn)賣票,?代碼步驟如下
????@Override
????public?void?run()?{
????????while(true)?{
????????????//tickes=100
????????????//t1,t2,t3
????????????//假設(shè)t1搶到CPU執(zhí)行器
????????????synchronized?(obj){
????????????????//t1進(jìn)來后把代碼鎖起來了
????????????????if?(tickets?>?0)?{
????????????????????try?{
????????????????????????Thread.sleep(100);
????????????????????????//t1休息100毫秒
????????????????????}?catch?(InterruptedException?e)?{
????????????????????????e.printStackTrace();
????????????????????}
????????????????????//窗口1正在出售第100張票
????????????????????System.out.println(Thread.currentThread().getName()?+?"正在出售第"?+?tickets?+?"張票");
????????????????????tickets--;?//tickets=99
????????????????}
????????????????//t1出來了,鎖就被釋放了
????????????}
????????}
????}}
  • 測試類
package?test;public?class?SellTicketDemo?{
????public?static?void?main(String[]?args)?{
????????//創(chuàng)建SellTicket類的對象
????????SellTicket?st?=?new?SellTicket();

????????//創(chuàng)建三個(gè)Thread類的對象,把SellTicket對象作為構(gòu)造方法的參數(shù),并給出對應(yīng)的窗口名稱
????????Thread?t1?=?new?Thread(st,"窗口1");
????????Thread?t2?=?new?Thread(st,"窗口2");
????????Thread?t3?=?new?Thread(st,"窗口3");

????????//啟動(dòng)線程
????????t1.start();
????????t2.start();
????????t3.start();

????}}

1.10 線程同步_同步方法

  • 作用:把出現(xiàn)線程安全問題的核心方法給鎖起來,每次只能一個(gè)線程進(jìn)入訪問,其他線程必須在方法外面等待
  • 同步方法:就是把synchronized關(guān)鍵字加到方法上;鎖對象為:this ?
    • 格式:修飾符 synchronized 返回值類型 方法名(方法參數(shù)) {}
  • 同步靜態(tài)方法:就是把synchronized關(guān)鍵字加到靜態(tài)方法上面;鎖對象為:類名.class ?
    • 格式:修飾符 static synchronized 返回值類型 方法名(方法參數(shù)) {}
package?test;public?class?SellTicket?implements?Runnable{//1非靜態(tài)????private?int?tickets?=?100;
????private?static?int?tickets?=?100;
????private?Object?obj?=?new?Object();
????private?int?x?=?0;

????@Override
????public?void?run()?{
????????while(true)?{
????????????if(x%2==0)?{//1非靜態(tài)????????????????synchronized?(this)?{
????????????????synchronized?(SellTicket.class)?{
????????????????????if?(tickets?>?0)?{
????????????????????????try?{
????????????????????????????Thread.sleep(100);
????????????????????????}?catch?(InterruptedException?e)?{
????????????????????????????e.printStackTrace();
????????????????????????}
????????????????????????System.out.println(Thread.currentThread().getName()?+?"正在出售第"?+?tickets?+?"張票");
????????????????????????tickets--;?//tickets=99
????????????????????}
????????????????}
????????????}?else?{//????????????????synchronized?(obj)?{//????????????????????if?(tickets?>?0)?{//????????????????????????try?{//????????????????????????????Thread.sleep(100);//????????????????????????}?catch?(InterruptedException?e)?{//????????????????????????????e.printStackTrace();//????????????????????????}//????????????????????????System.out.println(Thread.currentThread().getName()?+?"正在出售第"?+?tickets?+?"張票");//????????????????????????tickets--;?//tickets=99//????????????????????}//????????????????}
????????????????sellTicket();
????????????}
????????????x++;
????????}
????}//1非靜態(tài)//????private?synchronized?void?sellTicket()?{//????????if?(tickets?>?0)?{//????????????try?{//????????????????Thread.sleep(100);//????????????}?catch?(InterruptedException?e)?{//????????????????e.printStackTrace();//????????????}//????????????System.out.println(Thread.currentThread().getName()?+?"正在出售第"?+?tickets?+?"張票");//????????????tickets--;?//tickets=99//????????}//????}

????private?static?synchronized?void?sellTicket()?{
????????if?(tickets?>?0)?{
????????????try?{
????????????????Thread.sleep(100);
????????????}?catch?(InterruptedException?e)?{
????????????????e.printStackTrace();
????????????}
????????????System.out.println(Thread.currentThread().getName()?+?"正在出售第"?+?tickets?+?"張票");
????????????tickets--;?//tickets=99
????????}
????}}

1.11 線程安全的類(了解)

源碼中方法都被synchronized修飾

StringBuffer

  • 線程安全, 可變的字符序列
  • 從版本JDK 5開始,被StringBuilder替代。通常應(yīng)該使用StringBuilder類, 因?yàn)樗С炙邢嗤牟僮?但它更快,因?yàn)樗粓?zhí)行同步

Vector

  • 從Java 2平臺v1.2開始,該類改進(jìn)了List接口, 使其成為Java Collections Framework的成員。 與新的集合實(shí)現(xiàn)不同,Vector被同步。 如果不需要線程安全的實(shí)現(xiàn),建議使用ArrayList代替Vector

Hashtable

  • 該類實(shí)現(xiàn)了一個(gè)哈希表,它將鍵映射到值。任何非null對象都可以用作鍵或者值
  • 從Java 2平臺v1.2開始,該類進(jìn)行了改進(jìn),實(shí)現(xiàn)了Map接口,使其成為Java Collections Framework的成員。與新的集合實(shí)現(xiàn)不同,Hashtable被同步。 如果不需要線程安全的實(shí)現(xiàn),建議使用HashMap代替Hashtable

Collections類中static <t> List<t> snchronizedList(List<t> list)</t></t></t>:返回由指定列表支持的同步(線程安全)的列表

package?test;import?java.util.ArrayList;import?java.util.Collection;import?java.util.Collections;public?class?Demo?{
????public?static?void?main(String[]?args)??{
????????//static?<t>?List<t>?snchronizedList(List<t>?list):返回由指定列表支持的同步(線程安全)的列表
????????Collection<string>?list?=?Collections.synchronizedList(new?ArrayList<string>());

????????/*源碼都是返回Synchronized
????????public?static?<t>?List<t>?synchronizedList(List<t>?list)?{
????????????return?(list?instanceof?RandomAccess??
????????????????????new?Collections.SynchronizedRandomAccessList(list)?:
????????????????????new?Collections.SynchronizedList(list));
????????}*/

????}}</t></t></t></string></string></t></t></t>

1.12 Lock鎖

  • Lock是接口不能直接實(shí)例化,采用實(shí)現(xiàn)類ReentrantLock來實(shí)例化(JDK5以后)
  • ReentrantLock構(gòu)造方法:
方法名 說明
ReentrantLock() 創(chuàng)建一個(gè)ReentrantLock的實(shí)例對象
  • Lock中獲得鎖和釋放鎖方法:
方法名 說明
void lock() 獲得鎖
void unlock() 釋放鎖
  • 推薦使用try{} finall{}代碼塊來加鎖和釋放鎖
package?test;import?java.util.concurrent.locks.Lock;import?java.util.concurrent.locks.ReentrantLock;public?class?SellTicket?implements?Runnable{
????private?static?int?tickets?=?100;
????private?Lock?lock?=?new?ReentrantLock();

????@Override
????public?void?run()?{
????????while(true)?{
????????????try?{
????????????????lock.lock();
????????????????if?(tickets?>?0)?{
????????????????????try?{
????????????????????????Thread.sleep(100);
????????????????????}?catch?(InterruptedException?e)?{
????????????????????????e.printStackTrace();
????????????????????}
????????????????????System.out.println(Thread.currentThread().getName()?+?"正在出售第"?+?tickets?+?"張票");
????????????????????tickets--;
????????????????}
????????????}finally?{
????????????????lock.unlock();
????????????}
????????}
????}}

1.13 線程通訊

  • 線程通信一定是多個(gè)線程在操作同一個(gè)資源才需要通信
方法名 說明
public void wait() 讓當(dāng)前線程進(jìn)入到等待狀態(tài),此方法必須鎖對象調(diào)用
public void notify() 喚醒當(dāng)前鎖對象上等待狀態(tài)的某個(gè)線程,此方法必須鎖對象調(diào)用
public void notifyAll() 喚醒當(dāng)前鎖對象上等待狀態(tài)的全部線程,此方法必須鎖對象調(diào)用

1.14 生產(chǎn)者消費(fèi)者

1.14.1 生產(chǎn)者消費(fèi)者概述

Teknik klasik Java untuk mencapai penyegerakan berbilang benang dan benang

  • 為了體現(xiàn)生產(chǎn)和消費(fèi)過程中的等待和喚醒,Java就提供了幾個(gè)方法供我們使用,這幾個(gè)方法在Object類中
  • Object類的等待和喚醒方法
方法名 說明
void wait() 導(dǎo)致當(dāng)前線程等待,直到另一個(gè)線程調(diào)用該對象的 notify() 方法或 notifyAll() 方法
void notify() 喚醒正在等待對象監(jiān)視器的單個(gè)線程
void notifyAll() 喚醒正在等待對象監(jiān)視器的所有線程

1.14.2 生產(chǎn)者消費(fèi)者案例

Teknik klasik Java untuk mencapai penyegerakan berbilang benang dan benang

  • 奶箱類
package?test;//1:定義奶箱類public?class?Box?{
????//定義一個(gè)成員變量,表示第x瓶奶
????private?int?milk;
????//定義一個(gè)成員變量表示奶箱的狀態(tài)
????private?boolean?state?=?false;

????//提供存儲牛奶和獲取牛奶的操作
????public??synchronized?void?put(int?milk)?{
????????//如果有牛奶等待消費(fèi)
????????if(state)?{
????????????try?{
????????????????wait();
????????????}?catch?(InterruptedException?e)?{
????????????????e.printStackTrace();
????????????}
????????}

????????//如果沒有牛奶,就生產(chǎn)牛奶
????????this.milk?=?milk;
????????System.out.println("送奶工將第"?+?this.milk?+?"瓶奶放入奶箱");

????????//生產(chǎn)完畢后,修改奶箱狀態(tài)
????????state?=?true;

????????//喚醒其他等待線程
????????notifyAll();
????}

????public??synchronized?void?get()?{
????????//如果沒有牛奶,就等到生產(chǎn)
????????if(!state)?{
????????????try?{
????????????????wait();
????????????}?catch?(InterruptedException?e)?{
????????????????e.printStackTrace();
????????????}
????????}
????????//如果有牛奶,就消費(fèi)牛奶
????????System.out.println("用戶拿到第"?+?this.milk?+?"瓶奶");

????????//消費(fèi)完畢后,修改奶箱狀態(tài)
????????state?=?false;

????????//喚醒其他等待線程
????????notifyAll();
????}}
  • 生產(chǎn)者類
package?test;//2:生產(chǎn)者類(Producer):實(shí)現(xiàn)Runnable接口public?class?Producer?implements?Runnable?{
????private?Box?b;

????public?Producer(Box?b)?{
????????this.b?=?b;
????}

????//重寫run()方法,調(diào)用存儲牛奶的操作
????@Override
????public?void?run()?{
????????for?(int?i?=?1;?i?
  • 消費(fèi)者類
package?test;//3:消費(fèi)者類(Customer);實(shí)現(xiàn)Runnable接口public?class?Customer?implements?Runnable{
????private?Box?b;

????public?Customer(Box?b)?{
????????this.b?=?b;
????}

????//重寫run()方法,調(diào)用獲取牛奶的操作
????@Override
????public?void?run()?{
????????while(true)?{
????????????b.get();
????????}
????}}
  • 測試類
package?test;public?class?BoxDemo?{
????public?static?void?main(String[]?args)?{
????????//創(chuàng)建奶箱對象,這是共享數(shù)據(jù)區(qū)域
????????Box?b?=?new?Box();

????????//創(chuàng)建生產(chǎn)者對象,把奶箱對象作為構(gòu)造方法參數(shù)傳遞。因?yàn)樵谶@個(gè)類中要謂用存儲牛奶的操作
????????Producer?p?=?new?Producer(b);

????????//創(chuàng)建消費(fèi)者對象,把奶箱對象作為構(gòu)造方法參數(shù)傳遞,因?yàn)樵谶@個(gè)類中要調(diào)用獲取牛奶的操作
????????Customer?c??=new?Customer(b);

????????//創(chuàng)建2個(gè)線程對象,分別把生產(chǎn)者對象和消費(fèi)者對象作為構(gòu)造方法參數(shù)傳遞
????????Thread?t1?=?new?Thread(p);
????????Thread?t2?=?new?Thread(c);

????????//啟動(dòng)線程
????????t1.start();
????????t2.start();//????????送奶工將第1瓶奶放入奶箱//????????????????用戶拿到第1瓶奶//????????送奶工將第2瓶奶放入奶箱//????????????????用戶拿到第2瓶奶//????????送奶工將第3瓶奶放入奶箱//????????????????用戶拿到第3瓶奶//????????送奶工將第4瓶奶放入奶箱//????????????????用戶拿到第4瓶奶//????????送奶工將第5瓶奶放入奶箱//????????????????用戶拿到第5瓶奶
????}}

推薦學(xué)習(xí):《java視頻教程

Atas ialah kandungan terperinci Teknik klasik Java untuk mencapai penyegerakan berbilang benang dan benang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Tutorial PHP
1502
276
Bagaimana menangani transaksi di Java dengan JDBC? Bagaimana menangani transaksi di Java dengan JDBC? Aug 02, 2025 pm 12:29 PM

Untuk mengendalikan transaksi JDBC dengan betul, anda mesti terlebih dahulu mematikan mod komit automatik, kemudian melakukan pelbagai operasi, dan akhirnya melakukan atau mengembalikan semula hasilnya; 1. Panggil Conn.SetAutOcommit (palsu) untuk memulakan transaksi; 2. Melaksanakan pelbagai operasi SQL, seperti memasukkan dan mengemaskini; 3. Panggil Conn.Commit () jika semua operasi berjaya, dan hubungi conn.rollback () jika pengecualian berlaku untuk memastikan konsistensi data; Pada masa yang sama, cuba-dengan-sumber harus digunakan untuk menguruskan sumber, mengendalikan pengecualian dengan betul dan menutup sambungan untuk mengelakkan kebocoran sambungan; Di samping itu, adalah disyorkan untuk menggunakan kolam sambungan dan menetapkan mata simpan untuk mencapai rollback separa, dan menyimpan urus niaga sesingkat mungkin untuk meningkatkan prestasi.

Bagaimana untuk bekerja dengan kalendar di Jawa? Bagaimana untuk bekerja dengan kalendar di Jawa? Aug 02, 2025 am 02:38 AM

Gunakan kelas dalam pakej Java.Time untuk menggantikan kelas lama dan kelas kalendar; 2. Dapatkan tarikh dan masa semasa melalui LocalDate, LocalDateTime dan Tempatan Tempatan; 3. Buat tarikh dan masa tertentu menggunakan kaedah (); 4. Gunakan kaedah tambah/tolak untuk meningkatkan dan mengurangkan masa; 5. Gunakan zoneddatetime dan zonid untuk memproses zon waktu; 6. Format dan parse date string melalui DateTimeFormatter; 7. Gunakan segera untuk bersesuaian dengan jenis tarikh lama apabila perlu; pemprosesan tarikh di java moden harus memberi keutamaan untuk menggunakan java.timeapi, yang memberikan jelas, tidak berubah dan linear

Membandingkan kerangka Java: Spring Boot vs Quarkus vs Micronaut Membandingkan kerangka Java: Spring Boot vs Quarkus vs Micronaut Aug 04, 2025 pm 12:48 PM

Pra-formancetartuptimemoryusage, quarkusandmicronautleadduetocompile-timeprocessingandgraalvsupport, withquarkusoftenperforminglightbetterine serverless scenarios.tyvelopecosyste,

Bagaimana pengumpulan sampah berfungsi di java? Bagaimana pengumpulan sampah berfungsi di java? Aug 02, 2025 pm 01:55 PM

Koleksi Sampah Java (GC) adalah mekanisme yang secara automatik menguruskan ingatan, yang mengurangkan risiko kebocoran ingatan dengan menuntut semula objek yang tidak dapat dicapai. 1.GC menghakimi kebolehcapaian objek dari objek akar (seperti pembolehubah stack, benang aktif, medan statik, dan lain -lain), dan objek yang tidak dapat dicapai ditandakan sebagai sampah. 2. Berdasarkan algoritma penandaan tanda, tandakan semua objek yang dapat dicapai dan objek yang tidak ditandai. 3. Mengamalkan strategi pengumpulan generasi: Generasi Baru (Eden, S0, S1) sering melaksanakan MinorGC; Orang tua melakukan kurang tetapi mengambil masa lebih lama untuk melakukan MajorGC; Metaspace Stores Metadata kelas. 4. JVM menyediakan pelbagai peranti GC: SerialGC sesuai untuk aplikasi kecil; ParallelGC meningkatkan throughput; CMS mengurangkan

Pergi dengan contoh contoh pembalakan middleware http Pergi dengan contoh contoh pembalakan middleware http Aug 03, 2025 am 11:35 AM

HTTP Log Middleware di GO boleh merakam kaedah permintaan, laluan, IP klien dan memakan masa. 1. Gunakan http.handlerfunc untuk membungkus pemproses, 2. Rekod waktu mula dan masa akhir sebelum dan selepas memanggil next.servehttp, 3. Dapatkan IP pelanggan sebenar melalui r.remoteaddr dan X-forward-for headers, 4. Gunakan log.printf untuk mengeluarkan log permintaan, 5. Kod sampel lengkap telah disahkan untuk dijalankan dan sesuai untuk memulakan projek kecil dan sederhana. Cadangan lanjutan termasuk menangkap kod status, menyokong log JSON dan meminta penjejakan ID.

Menggunakan jenis html `input` untuk data pengguna Menggunakan jenis html `input` untuk data pengguna Aug 03, 2025 am 11:07 AM

Memilih jenis htmlinput yang betul dapat meningkatkan ketepatan data, meningkatkan pengalaman pengguna, dan meningkatkan kebolehgunaan. 1. Pilih jenis input yang sepadan mengikut jenis data, seperti teks, e -mel, tel, nombor dan tarikh, yang secara automatik boleh menyemak dan menyesuaikan diri dengan papan kekunci; 2. Gunakan HTML5 untuk menambah jenis baru seperti URL, Warna, Julat dan Carian, yang dapat memberikan kaedah interaksi yang lebih intuitif; 3. Gunakan pemegang tempat dan sifat -sifat yang diperlukan untuk meningkatkan kecekapan dan ketepatan pengisian bentuk, tetapi harus diperhatikan bahawa pemegang tempat tidak dapat menggantikan label.

Membandingkan Java Build Tools: Maven vs Gradle Membandingkan Java Build Tools: Maven vs Gradle Aug 03, 2025 pm 01:36 PM

GradleisthebetterChoiceFormostNewProjectSduetoitSsuperiorflexibility, Prestasi, danModernToolingSupport.1.Gradle'sGroovy/KOT lindslismoreconciseandexpressivethanmaven'sverbosexml.2.GradleOutPerformsMaveninBuildSpeedWithIncrementalcompilation, BuildCac

Pergi dengan contoh penangguhan yang dijelaskan Pergi dengan contoh penangguhan yang dijelaskan Aug 02, 2025 am 06:26 AM

Defer digunakan untuk melaksanakan operasi tertentu sebelum fungsi pulangan, seperti sumber pembersihan; Parameter dinilai dengan serta-merta apabila menangguhkan, dan fungsi-fungsi dilaksanakan mengikut urutan terakhir (LIFO); 1. Pelbagai penahanan dilaksanakan dalam urutan terbalik pengisytiharan; 2. Biasanya digunakan untuk pembersihan yang selamat seperti penutupan fail; 3. Nilai pulangan yang dinamakan boleh diubah suai; 4. Ia akan dilaksanakan walaupun panik berlaku, sesuai untuk pemulihan; 5. Elakkan penyalahgunaan menangguhkan gelung untuk mengelakkan kebocoran sumber; Penggunaan yang betul boleh meningkatkan keselamatan kod dan kebolehbacaan.

See all articles