国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java線程之間通信方式

這篇具有很好參考價(jià)值的文章主要介紹了Java線程之間通信方式。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。


1 線程之間的通信方式主要有以下幾種

Java線程之間通信方式,java,java,開(kāi)發(fā)語(yǔ)言

在實(shí)際開(kāi)發(fā)時(shí),一個(gè)進(jìn)程中往往有很多個(gè)線程,大多數(shù)線程之間往往不是絕對(duì)獨(dú)立的,比如說(shuō)我們需要將A和B 兩個(gè)線程的執(zhí)行結(jié)果收集在一起然后顯示在界面上,又或者比較典型的消費(fèi)者-生產(chǎn)者模式,在這些場(chǎng)景下,線程間通信成了我們必須使用的手段,那么線程之間怎么通信呢?

線程間通信方式,從實(shí)現(xiàn)本質(zhì)來(lái)講,主要可以分為兩大類(lèi)共享內(nèi)存和消息傳遞。

相信大家還記得,在內(nèi)存模型一節(jié),我們提到多線程并發(fā)情況下的三大特性,原子性,有序性,可見(jiàn)性,其所對(duì)應(yīng)的解決方案就可以用來(lái)實(shí)現(xiàn)線程間通信,這些解決方案的本質(zhì)就是共享內(nèi)存。

對(duì)于消息傳遞而言,最經(jīng)典的實(shí)現(xiàn)就是我們的Handler機(jī)制,在子線程使用主線程的Handler對(duì)象將一些信息發(fā)送到主線程以便進(jìn)行處理。

下面我們來(lái)看一些線程間通信的典型實(shí)現(xiàn)

2 共享變量

共享變量:線程之間可以通過(guò)共享變量來(lái)進(jìn)行通信。不同的線程可以共享同一個(gè)變量,并在變量上進(jìn)行讀寫(xiě)操作。需要注意的是,共享變量可能會(huì)引發(fā)線程安全問(wèn)題,需要通過(guò)同步機(jī)制來(lái)確保線程安全。

public class SharedData {
    private int value;
    public synchronized int getValue() { 
        return value; 
    }
    public synchronized void setValue(int value) { 
        this.value = value; 
    }
}

? 在這個(gè)示例中,定義了一個(gè)共享數(shù)據(jù)類(lèi) SharedData,其中包含一個(gè)整型變量 value 和兩個(gè)同步方法 getValue()setValue(),用于獲取和設(shè)置變量的值。由于這兩個(gè)方法都是同步的,因此多個(gè)線程可以安全地訪問(wèn)該變量。

public class SharedDataExample {
    public static void main(String[] args) throws InterruptedException {
        SharedData sharedData = new SharedData();
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                sharedData.setValue(i);
                System.out.println(Thread.currentThread().getName() + " write " + sharedData.getValue());
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName() + " read " + sharedData.getValue());
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
    }
}

? 在這個(gè)示例中,創(chuàng)建了兩個(gè)線程分別用于讀寫(xiě)共享數(shù)據(jù) SharedData,多次執(zhí)行該示例可以看到控制臺(tái)輸出表明兩個(gè)線程在安全地訪問(wèn)共享變量。

結(jié)果如圖:
Java線程之間通信方式,java,java,開(kāi)發(fā)語(yǔ)言

3 鎖機(jī)制

鎖機(jī)制:鎖機(jī)制是一種常用的線程同步機(jī)制,可以保證在同一時(shí)間只有一個(gè)線程能夠訪問(wèn)共享資源。Java提供了多種鎖類(lèi)型,如 synchronized 關(guān)鍵字、ReentrantLock 類(lèi)等。

public class LockExample {
    private static Lock lock = new ReentrantLock();
    private static int count = 0;
    private static void increase() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                increase();
            }
        });
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                increase();
            }
        });
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(count);
    }
}

? 在這個(gè)示例中,使用了 Lock 接口和 ReentrantLock 類(lèi)來(lái)對(duì)計(jì)數(shù)器進(jìn)行同步,多次執(zhí)行該示例可以看到最終輸出的計(jì)數(shù)器值為 20000。

結(jié)果如圖:
Java線程之間通信方式,java,java,開(kāi)發(fā)語(yǔ)言

4 條件變量

條件變量:條件變量是一種線程間通信機(jī)制,它用于在一個(gè)共享資源上等待某個(gè)條件的成立。Java 提供了 Condition 接口來(lái)支持條件變量的實(shí)現(xiàn),在使用 Condition 時(shí)需要先獲取鎖,然后調(diào)用 await() 方法等待條件成立,當(dāng)條件成立時(shí)可以通過(guò) signal() 或 signalAll() 方法喚醒等待該條件的線程。

public class ConditionExample {
    private static Lock lock = new ReentrantLock();
    private static Condition condition = lock.newCondition();
    private static int count = 0;
    private static void await() throws InterruptedException {
        lock.lock();
        try {
            condition.await();
        } finally {
            lock.unlock();
        }
    }
    private static void signal() {
        lock.lock();
        try {
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count++;
                System.out.println(Thread.currentThread().getName() + " increase count to " + count);
                if (count == 5) {
                    signal();
                }
            }
        });
        Thread thread2 = new Thread(() -> {
            try {
                await();
                System.out.println(Thread.currentThread().getName() + " receive signal, count is " + count);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
    }
}

? 在這個(gè)示例中,使用了 Lock 接口和 Condition 接口來(lái)定義了一個(gè)計(jì)數(shù)器,線程1每次增加計(jì)數(shù)器的值并判斷是否達(dá)到條件,當(dāng)計(jì)數(shù)器達(dá)到條件時(shí)調(diào)用 signal() 方法通知線程2,線程2等待條件成立后執(zhí)行相應(yīng)的操作。

Java線程之間通信方式,java,java,開(kāi)發(fā)語(yǔ)言

5 信號(hào)量

信號(hào)量:信號(hào)量是一種常見(jiàn)的線程同步機(jī)制,可用于控制多個(gè)線程對(duì)共享資源的訪問(wèn)。Java 提供了 Semaphore 類(lèi)來(lái)實(shí)現(xiàn)信號(hào)量,Semaphore 類(lèi)有兩個(gè)常用的方法 acquire() 和 release(),分別用于獲取和釋放信號(hào)量。

public class SemaphoreExample {
    private static Semaphore semaphore = new Semaphore(2);
    private static void doWork() throws InterruptedException {
        semaphore.acquire();
        System.out.println(Thread.currentThread().getName() + " start working");
        Thread.sleep(1000);
        System.out.println(Thread.currentThread().getName() + " finish working");
        semaphore.release();
    }
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(() -> {
            try {
                doWork();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        Thread thread2 = new Thread(() -> {
            try {
                doWork();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        Thread thread3 = new Thread(() -> {
            try {
                doWork();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        thread1.start();
        thread2.start();
        thread3.start();
        thread1.join();
        thread2.join();
        thread3.join();
    }
}

? 在這個(gè)示例中,使用了 Semaphore 類(lèi)來(lái)定義了一個(gè)信號(hào)量,線程1、線程2、線程3都需要獲取信號(hào)量才能進(jìn)行工作,每次執(zhí)行 doWork() 方法需要占用資源,執(zhí)行完畢后釋放信號(hào)量。

Java線程之間通信方式,java,java,開(kāi)發(fā)語(yǔ)言

6 管道

管道:管道是一種用于線程間通信的高級(jí)機(jī)制,它可以實(shí)現(xiàn)一個(gè)線程向另一個(gè)線程傳送數(shù)據(jù)。Java 提供了 PipedInputStream 和 PipedOutputStream 兩個(gè)類(lèi)來(lái)支持管道的實(shí)現(xiàn),其中 PipedInputStream 用于讀取數(shù)據(jù),PipedOutputStream 用于寫(xiě)入數(shù)據(jù)。

public class PipeExample {
    static class WriterThread extends Thread {
        private PipedOutputStream output;
        WriterThread(PipedOutputStream output) {
            this.output = output;
        }
        @Override
        public void run() {
            try {
                for(int i=1;i<=10;i++) {
                    output.write(i);
                    System.out.println("寫(xiě)入數(shù)據(jù):" + i);
                    Thread.sleep(1000);
                }
            } catch(Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    output.close();
                } catch(Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    static class ReaderThread extends Thread {
        private PipedInputStream input;
        ReaderThread(PipedInputStream input) {
            this.input = input;
        }
        @Override
        public void run() {
            try {
                int value;
                while((value=input.read()) != -1) {
                    System.out.println("讀取數(shù)據(jù):" + value);
                }
            } catch(Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    input.close();
                } catch(Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) throws IOException {
        PipedOutputStream output = new PipedOutputStream();
        PipedInputStream input = new PipedInputStream(output);
        Thread thread1 = new WriterThread(output);
        Thread thread2 = new ReaderThread(input);
        thread1.start();
        thread2.start();
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在這個(gè)示例中,使用了 PipedOutputStream 類(lèi)和 PipedInputStream 類(lèi)來(lái)定義了一個(gè)管道,線程1向管道中寫(xiě)入數(shù)據(jù),線程2從管道中讀取數(shù)據(jù),通過(guò)管道來(lái)實(shí)現(xiàn)兩個(gè)線程之間的通信。

運(yùn)行結(jié)果:Java線程之間通信方式,java,java,開(kāi)發(fā)語(yǔ)言

需要注意的是,以上通信方式都需要在多線程程序中謹(jǐn)慎使用,需要考慮線程安全和性能等方面的問(wèn)題。為了確保程序正確、高效地運(yùn)行,需要根據(jù)具體情況選擇合適的線程通信方式,并進(jìn)行相應(yīng)的測(cè)試和優(yōu)化。

6 join方法的實(shí)現(xiàn)原理

說(shuō)了這么多,也舉了這么多例子了,join方法是怎么實(shí)現(xiàn)線程等待的呢?我點(diǎn)進(jìn)去join方法內(nèi)部可以看到,其實(shí)它的內(nèi)部也就是調(diào)用了wait()方法,

Java線程之間通信方式,java,java,開(kāi)發(fā)語(yǔ)言

只不過(guò)它多做了一步,用了一個(gè)循環(huán)來(lái)判斷線程是否還活著,isAlive()方法就是用來(lái)判斷線程是否還活著;

Java線程之間通信方式,java,java,開(kāi)發(fā)語(yǔ)言

7 join方法實(shí)現(xiàn)順序性原理

那么這個(gè)時(shí)候肯定有的同學(xué)就有疑問(wèn)了,只看到j(luò)oin()方法調(diào)用了wait()方法,但是沒(méi)看到有調(diào)用notify() 或者 notifyAll() 系列的喚醒方法,那它是怎么喚醒的呢?如果不喚醒,那不就一直等待下去了嗎?

*原來(lái)啊,在java中,Thread類(lèi)線程執(zhí)行完run()方法后,一定會(huì)自動(dòng)執(zhí)行notifyAll()方法*

這是notifyAll()非常重要的隱藏知識(shí)點(diǎn),這個(gè)細(xì)節(jié)隱藏在Java的Native方法中,所以一般不會(huì)被人發(fā)現(xiàn)。我們觀察C/C++源碼,如下:


oid JavaThread::exit(booldestory_vm, ExitTypeexit_type);
static void ensure_join(JavaThread*thread) {
	Handle threadObj(thread, thread -> threadObj());
	ObjectLocker lock(threadObj, thread);
	thread -> clear_pending_exception();
	java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED);
	java_lang_Thread::set_thread(threadObj(), NULL);
     //下行執(zhí)行了notifyAll()操作
	lock.notify_all(thread);
	thread -> clear_pending_exception();
	}

其中ensure_join就是執(zhí)行join()方法,等方法執(zhí)行結(jié)束時(shí),此行代碼lock.notify_all(thread);意思是通過(guò)notifyAll()喚醒了所有等待線程。所以在使用線程的時(shí)候,要特別注意文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-704537.html

到了這里,關(guān)于Java線程之間通信方式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • java死鎖、線程狀態(tài)、線程通信、線程池

    java實(shí)現(xiàn)多線程: [1]繼承Thread類(lèi)并重寫(xiě)run方法 [2]實(shí)現(xiàn)Runnable接口 線程Thread中常用的方法: setName(): Thread.currentThread().getName(): ? static void sleep(); static void yield(): join(): setDeamon()設(shè)置后臺(tái)線程 線程安全問(wèn)題: ---當(dāng)多個(gè)線程共享同一個(gè)資源時(shí),對(duì)該資源的操作就會(huì)出現(xiàn)線程安全問(wèn)題。

    2024年02月13日
    瀏覽(24)
  • [Java]線程生命周期與線程通信

    [Java]線程生命周期與線程通信

    【版權(quán)聲明】未經(jīng)博主同意,謝絕轉(zhuǎn)載?。ㄕ?qǐng)尊重原創(chuàng),博主保留追究權(quán)) https://www.cnblogs.com/cnb-yuchen/p/18162522 出自【進(jìn)步*于辰的博客】 線程生命周期與進(jìn)程有諸多相似,所以我們很容易將兩者關(guān)聯(lián)理解并混淆,一些細(xì)節(jié)之處確有許多不同,因?yàn)榫€程調(diào)度與進(jìn)程調(diào)度雖都由

    2024年04月27日
    瀏覽(20)
  • Java 進(jìn)階(12) 線程通信

    多個(gè)線程在處理同?個(gè)資源,但是處理的動(dòng)作(線程的任務(wù))卻不相同。 為什么要處理線程間通信 多個(gè)線程并發(fā)執(zhí)?時(shí), 在默認(rèn)情況下CPU是隨機(jī)切換線程的,當(dāng)我們需要多個(gè)線程來(lái)共同完成?件任務(wù),并且我們希望他們有規(guī)律的執(zhí)?, 那么多線程之間需要?些協(xié)調(diào)通信,以此

    2023年04月16日
    瀏覽(21)
  • 【Java】詳解多線程通信

    【Java】詳解多線程通信

    ?? 個(gè)人主頁(yè): Dawn黎明開(kāi)始 ?? 系列專欄: Java ? 每日一句:什么都不做,才會(huì)來(lái)不及 ?? 歡迎大家:關(guān)注 ??+ 點(diǎn)贊 ??+評(píng)論 ??+收藏?? 文章目錄 ??多線程通信 (1).??由來(lái) (2).??成員方法? (3).??案例引入 (4).??代碼實(shí)現(xiàn) ? ? ? 現(xiàn)代社會(huì)崇尚合作精神,分工合作在日常

    2024年02月05日
    瀏覽(21)
  • Java多線程 - Java創(chuàng)建線程的4種方式

    Java多線程 - Java創(chuàng)建線程的4種方式

    1. Java創(chuàng)建線程有哪幾種方式? 一個(gè)線程在Java中使用一個(gè)Thread實(shí)例來(lái)描述。Thread類(lèi)是Java語(yǔ)言的一個(gè)重要的基礎(chǔ)類(lèi),位于java.lang包中。Thread類(lèi)有不少非常重要的屬性和方法,用于存儲(chǔ)和操作線程的描述信息。 Thread類(lèi)的構(gòu)造方法: 1.1 線程創(chuàng)建方法一:繼承Thread類(lèi)創(chuàng)建線程類(lèi) (

    2023年04月08日
    瀏覽(19)
  • 深入理解Java線程間通信

    合理的使用Java多線程可以更好地利用服務(wù)器資源。一般來(lái)講,線程內(nèi)部有自己私有的線程上下文,互不干擾。但是當(dāng)我們需要多個(gè)線程之間相互協(xié)作的時(shí)候,就需要我們掌握J(rèn)ava線程的通信方式。本文將介紹Java線程之間的幾種通信原理。 在Java中,鎖的概念都是基于對(duì)象的,

    2024年02月09日
    瀏覽(25)
  • java 線程安全問(wèn)題 三種線程同步方案 線程通信(了解)

    java 線程安全問(wèn)題 三種線程同步方案 線程通信(了解)

    線程安全問(wèn)題指的是,多個(gè)線程同時(shí)操作同一個(gè)共享資源的時(shí)候,可能會(huì)出現(xiàn)業(yè)務(wù)安全問(wèn)題。 下面代碼演示上述問(wèn)題,先定義一個(gè)共享的賬戶類(lèi): 在定義一個(gè)取錢(qián)的線程類(lèi) 最后,再寫(xiě)一個(gè)測(cè)試類(lèi),在測(cè)試類(lèi)中創(chuàng)建兩個(gè)線程對(duì)象 某個(gè)執(zhí)行結(jié)果: 為了解決前面的線程安全問(wèn)題,

    2024年02月09日
    瀏覽(16)
  • 面試官:Java 線程有哪幾種狀態(tài)?它們之間是怎么切換的?

    面試官:Java 線程有哪幾種狀態(tài)?它們之間是怎么切換的?

    來(lái)源:https://blog.csdn.net/limenghua9112/article/details/106975105 線程是 JVM 執(zhí)行任務(wù)的最小單元,理解線程的狀態(tài)轉(zhuǎn)換是理解后續(xù)多線程問(wèn)題的基礎(chǔ)。 在 JVM 運(yùn)行中,線程一共有 NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED 六種狀態(tài),這些狀態(tài)對(duì)應(yīng) Thread.State 枚舉類(lèi)中的狀態(tài)。 推薦

    2024年02月12日
    瀏覽(20)
  • 多線程之間如何進(jìn)行通信 ?

    實(shí)現(xiàn)多線程之間通信的方式有多種,以下是一些常見(jiàn)的方式: 共享變量:多個(gè)線程共享一個(gè)變量,通過(guò)互斥鎖(如 synchronized )來(lái)保護(hù)對(duì)該變量的訪問(wèn),確保線程之間的安全通信。 wait() 和 notify() / notifyAll() :通過(guò) Object 類(lèi)的 wait() 方法使線程等待,然后使用 notify() 或

    2024年02月09日
    瀏覽(23)
  • Java——》線程間是如何通信的

    Java——》線程間是如何通信的

    推薦鏈接: ????總結(jié)——》【Java】 ????總結(jié)——》【Mysql】 ????總結(jié)——》【Redis】 ????總結(jié)——》【Kafka】 ????總結(jié)——》【Spring】 ????總結(jié)——》【SpringBoot】 ????總結(jié)——》【MyBatis、MyBatis-Plus】 ????總結(jié)——》【Linux】 ????總結(jié)——》【MongoDB】 ???

    2024年02月09日
    瀏覽(19)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包