教育行業(yè)A股IPO第一股(股票代碼 003032)

全國咨詢/投訴熱線:400-618-4000

Java是如何實(shí)現(xiàn)線程間通信的?

更新時(shí)間:2023年07月14日09時(shí)43分 來源:傳智教育 瀏覽次數(shù):

好口碑IT培訓(xùn)

  在Java中,線程間通信可以通過以下方式實(shí)現(xiàn):

  1.共享變量

  線程可以通過共享的變量進(jìn)行通信。多個(gè)線程可以讀寫同一個(gè)變量來交換信息。在這種情況下,需要確保線程對(duì)共享變量的訪問是同步的,以避免數(shù)據(jù)競(jìng)爭和不一致的結(jié)果。

  以下是一個(gè)使用共享變量進(jìn)行線程通信的示例代碼:

class Message {
    private String content;
    private boolean hasNewMessage = false;

    public synchronized void putMessage(String content) {
        while (hasNewMessage) {
            try {
                wait(); // 等待直到消息被消費(fèi)
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        this.content = content;
        hasNewMessage = true;
        notifyAll(); // 喚醒等待的線程
    }

    public synchronized String getMessage() {
        while (!hasNewMessage) {
            try {
                wait(); // 等待直到有新消息
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        hasNewMessage = false;
        notifyAll(); // 喚醒等待的線程
        return content;
    }
}

class Producer implements Runnable {
    private Message message;

    public Producer(Message message) {
        this.message = message;
    }

    public void run() {
        String[] messages = { "Hello", "World", "Goodbye" };
        for (String msg : messages) {
            message.putMessage(msg);
            System.out.println("Producer: " + msg);
            try {
                Thread.sleep(1000); // 模擬耗時(shí)操作
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        message.putMessage("Done");
    }
}

class Consumer implements Runnable {
    private Message message;

    public Consumer(Message message) {
        this.message = message;
    }

    public void run() {
        String msg = "";
        while (!msg.equals("Done")) {
            msg = message.getMessage();
            System.out.println("Consumer: " + msg);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Message message = new Message();
        Thread producerThread = new Thread(new Producer(message));
        Thread consumerThread = new Thread(new Consumer(message));

        producerThread.start();
        consumerThread.start();
    }
}

  在這個(gè)示例中,有一個(gè)Message類,它表示一個(gè)消息對(duì)象。Message類中的putMessage方法用于生產(chǎn)消息,并將消息存儲(chǔ)在content變量中。getMessage方法用于消費(fèi)消息,并返回存儲(chǔ)的消息內(nèi)容。這兩個(gè)方法都使用synchronized關(guān)鍵字來實(shí)現(xiàn)同步,以確保線程安全。

  有一個(gè)Producer類,它實(shí)現(xiàn)了Runnable接口,用于在一個(gè)線程中生產(chǎn)消息。Consumer類也實(shí)現(xiàn)了Runnable接口,用于在另一個(gè)線程中消費(fèi)消息。

  在Main類的main方法中,創(chuàng)建了一個(gè)Message對(duì)象,并創(chuàng)建了一個(gè)生產(chǎn)者線程和一個(gè)消費(fèi)者線程。通過調(diào)用start方法啟動(dòng)這兩個(gè)線程,它們將并發(fā)地生產(chǎn)和消費(fèi)消息。

  在控制臺(tái)輸出中,我們將看到生產(chǎn)者線程和消費(fèi)者線程交替輸出消息,它們通過共享的Message對(duì)象進(jìn)行通信。

  2.等待/通知機(jī)制

  Java提供了wait、notify和notifyAll方法,用于線程間的等待和通知。線程可以調(diào)用wait方法暫停自己的執(zhí)行,直到另一個(gè)線程調(diào)用相同對(duì)象上的notify或notifyAll方法來喚醒它們。

  以下是一個(gè)使用等待/通知機(jī)制進(jìn)行線程通信的示例代碼:

class Message {
    private String content;
    private boolean hasNewMessage = false;

    public synchronized void putMessage(String content) {
        while (hasNewMessage) {
            try {
                wait(); // 等待直到消息被消費(fèi)
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        this.content = content;
        hasNewMessage = true;
        notifyAll(); // 喚醒等待的線程
    }

    public synchronized String getMessage() {
        while (!hasNewMessage) {
            try {
                wait(); // 等待直到有新消息
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        hasNewMessage = false;
        notifyAll(); // 喚醒等待的線程
        return content;
    }
}

class Producer implements Runnable {
    private Message message;

    public Producer(Message message) {
        this.message = message;
    }

    public void run() {
        String[] messages = { "Hello", "World", "Goodbye" };
        for (String msg : messages) {
            message.putMessage(msg);
            System.out.println("Producer: " + msg);
            try {
                Thread.sleep(1000); // 模擬耗時(shí)操作
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        message.putMessage("Done");
    }
}

class Consumer implements Runnable {
    private Message message;

    public Consumer(Message message) {
        this.message = message;
    }

    public void run() {
        String msg = "";
        while (!msg.equals("Done")) {
            msg = message.getMessage();
            System.out.println("Consumer: " + msg);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Message message = new Message();
        Thread producerThread = new Thread(new Producer(message));
        Thread consumerThread = new Thread(new Consumer(message));

        producerThread.start();
        consumerThread.start();
    }
}

  這個(gè)示例中的代碼與之前的示例相同。不同之處在于,putMessage和getMessage方法使用了wait和notifyAll方法來進(jìn)行線程間的等待和通知。當(dāng)putMessage方法調(diào)用wait時(shí),它會(huì)釋放對(duì)象的鎖并等待被喚醒。當(dāng)getMessage方法調(diào)用notifyAll時(shí),它會(huì)喚醒等待的線程并重新獲得對(duì)象的鎖。

  通過這種方式,生產(chǎn)者線程在沒有新消息時(shí)等待,直到消費(fèi)者線程消費(fèi)了消息并調(diào)用notifyAll方法。同樣,消費(fèi)者線程在沒有新消息時(shí)等待,直到生產(chǎn)者線程產(chǎn)生新消息并調(diào)用notifyAll方法。

  無論是共享變量還是等待/通知機(jī)制,Java提供了多種方法來實(shí)現(xiàn)線程間的通信。選擇適當(dāng)?shù)姆椒ㄈQ于特定的應(yīng)用場(chǎng)景和需求。

0 分享到:
和我們?cè)诰€交談!