简体   繁体   中英

Writer/Reader using Monitor not working

I´m doing an assignment where are implementing a Writer/Reader problem that uses a monitor for synchronization.

The scenario: The writer should write a string from a list one at a time into a buffer (the buffer can only hold one single string at a time). The reader should then read the string from the buffer and print the string in a gui with a 0.5 second pause between the prints. The program uses one singular writer-thread and one singular reader-thread, which are started simultaneously when a button in the gui is pressed.

My problem: I cannot get the synchronization to work, the reader just prints out null every 0.5 seconds (which means the buffer is most likely empty when the reader tries to read from it). I managed to find an error: the writer is not reaching the try where buffer.put(text.get(i)) , though I cannot figure out why.

Anyone who could help?? Much appreciated! My code is down below, hope it is enough, I don´t want to spam too much code. (I´m also pretty new with the Writer/Reader problem but have read some coding examples etc.)

Writer:

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();
        }
    }
}

Buffer:

/**
 * 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;
}

Reader:

/**
 * 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();
        }
    }
}

You can try this solution, just assign value to 'hasString' outside the while block.

 /**
 * 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;
}

The code works now (with help from @whaat answer), by only changing the code in the Buffer-class leaving both the Writer and Reader unchanged. I´ll leave the woring code for the buffer here in case someone else ever runs into the same problem as I did :)

/**
 * 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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM