【问题标题】:Writer/Reader using Monitor not working使用监视器的写入器/读取器不起作用
【发布时间】:2017-12-25 11:51:59
【问题描述】:

我正在执行一项任务,其中正在实施使用监视器进行同步的写入器/读取器问题。

场景: 编写者应该一次将列表中的一个字符串写入缓冲区(缓冲区一次只能保存一个字符串)。然后,读者应该从缓冲区中读取字符串并在 gui 中打印字符串,打印之间有 0.5 秒的暂停。该程序使用一个单一的写入线程和一个单一的读取线程,当按下 gui 中的按钮时,它们同时启动。

我的问题:我无法让同步工作,阅读器每 0.5 秒打印一次 null(这意味着当阅读器尝试从中读取时缓冲区很可能是空的)。我设法找到了一个错误:作者没有到达try 那里buffer.put(text.get(i)),虽然我不知道为什么。

谁能帮忙??非常感激!我的代码在下面,希望它足够了,我不想垃圾邮件太多代码。 (我对 Writer/Reader 问题也很陌生,但已经阅读了一些编码示例等)

作者:

public void run() {
    buffer.length(text.size());
    for (int i = 0; i < text.size(); i++) { //loops thorugh the list of strings
        System.out.println("hj"); //reaches this
        try {
            buffer.put(text.get(i)); //put the string into the buffer
            System.out.println("put done"); // never reaches this
            sleep(); //pauses the thread for 0.5 seconds
        } catch (InterruptedException e) {
            System.out.println("error"); //never reaches this either
            e.printStackTrace();
        }
    }
}

缓冲区:

/**
 * gets a string from the writer
 * @throws InterruptedException 
 */
public synchronized void put(String string) throws InterruptedException {
    while(hasString == false) { //we only want to put a string into the buffer if it is empty
        wait();
        this.string = string;
        hasString = true;
        notify();
    }
}

/**
 * passes on a string to the reader
 * @throws InterruptedException 
 */
public synchronized String get() throws InterruptedException {
    while(hasString == true) { //we only want to pass on a string if the buffer is NOT empty
        wait();
        hasString = false;
        notify();
    }
    return string;
}

读者:

/**
 * reads a string from the buffer and writes it to the gui in the destination-tab
 */
public void run() {
    for (int i  = 0; i < buffer.getLength(); i++) { //loops through the length of the list with strings
        try {
            string = buffer.get(); //gets string from buffer
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        //writes the string in the gui
        sb.append(string);
        GUIMonitor.txtPaneDest.setText(sb.toString());
        try {
            sleep(); //pauses the thread for 0.5 seconds
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

【问题讨论】:

  • 这段代码实际上做了几件事,非常好。但是条件检查没有任何意义。
  • 那么我离解决方案不远了。但是是的,缓冲区中的条件检查应该颠倒过来,请看我自己的答案@NathanHughes

标签: java multithreading synchronization monitor producer-consumer


【解决方案1】:

您可以尝试此解决方案,只需在 while 块之外为“hasString”赋值即可。

 /**
 * gets a string from the writer
 * @throws InterruptedException 
 */
public synchronized void put(String string) throws InterruptedException {
    while(hasString == false) { //we only want to put a string into the buffer if it is empty
        wait();
    }
    this.string = string;
    hasString = true;
    notify();

}

/**
 * passes on a string to the reader
 * @throws InterruptedException 
 */
public synchronized String get() throws InterruptedException {
    while(hasString == true) { //we only want to pass on a string if the buffer is NOT empty
        wait();
    }
    hasString = false;
    notify();
    return string;
}

【讨论】:

  • 我试过了,没有任何区别...@whaat
  • 但是我刚刚让它工作了!我遵循了您建议的解决方案并在while循环中切换了布尔值,因此put()中的hasString == false现在我有hasString == true,反之亦然get()方法。 @whaat
【解决方案2】:

代码现在可以工作(在@whaat 回答的帮助下),只需更改 Buffer 类中的代码,保持 Writer 和 Reader 不变。我会把缓冲区的工作代码留在这里,以防其他人遇到和我一样的问题:)

/**
 * gets a string from the writer
 * @throws InterruptedException 
 */
public synchronized void put(String string) throws InterruptedException {
    while(hasString == true) { //we only want to put a string into the buffer if it is empty
        wait();

    }
    this.string = string;
    hasString = true;
    notify();
}

/**
 * passes on a string to the reader
 * @throws InterruptedException 
 */
public synchronized String get() throws InterruptedException {
    while(hasString == false) { //we only want to pass on a string if the buffer is NOT empty
        wait();
    }
    hasString = false;
    notify();
    return string;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-08
    相关资源
    最近更新 更多