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

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

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

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

好口碑IT培訓(xùn)

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

  1.共享變量

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

  以下是一個使用共享變量進行線程通信的示例代碼:

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

    public synchronized void putMessage(String content) {
        while (hasNewMessage) {
            try {
                wait(); // 等待直到消息被消費
            } 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); // 模擬耗時操作
            } 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();
    }
}

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

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

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

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

  2.等待/通知機制

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

  以下是一個使用等待/通知機制進行線程通信的示例代碼:

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

    public synchronized void putMessage(String content) {
        while (hasNewMessage) {
            try {
                wait(); // 等待直到消息被消費
            } 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); // 模擬耗時操作
            } 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();
    }
}

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

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

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

0 分享到:
和我們在線交談!