Как устранить состояние гонки в учебнике Rox NIO - PullRequest
1 голос
/ 10 января 2012

Я использовал это руководство для простого клиента / сервера передачи файлов с использованием сокета IO.Я изменил обработчик ответа, чтобы принимать множественные чтения как часть одного файла, так как я буду иметь дело с большими файлами, потенциально до 500 МБ.В учебнике не учитывались большие ответы сервера, поэтому я немного борюсь, и я создал условие гонки.

Вот код обработчика ответа:

public class RspHandler {

private byte[] rsp = null;
public synchronized boolean handleResponse(byte[] rsp) {
    this.rsp = rsp;
    this.notify();
    return true;
}

public synchronized void waitForResponse() {
    while(this.rsp == null) {
        try {
            this.wait();
        } catch (InterruptedException e) {
        }
    }
    System.out.println("Received Response : " + new String(this.rsp));
}

public synchronized void waitForFile(String filename) throws IOException {
    String filepath = "C:\\a\\received\\" + filename;
    FileOutputStream fos = new FileOutputStream(filepath);
    while(waitForFileChunk(fos) != -1){}
    fos.close();
}

private synchronized int waitForFileChunk(FileOutputStream fos) throws IOException
{
    while(this.rsp == null) {
        try {
            this.wait();
        } catch (InterruptedException e) {
        }
    }
    fos.write(this.rsp);
    int length = this.rsp.length;
    this.rsp = null;
    if(length < NioClient.READ_SIZE)//Probably a bad way to find the end of the file
    {
        return -1;
    }
    else
    {
        return length;
    }

}
}

Основной поток программы создает RspHandler в основном потоке и передает его клиенту, созданному в отдельном потоке.Основной поток сообщает клиенту запросить файл, а затем сообщает RspHandler прослушать ответ.Когда клиент читает с сервера (прямо сейчас он читает частями около 1 КБ), он вызывает метод handleResponse(byte[] rsp), заполняющий байтовый массив rsp.

По сути, я не записываю полученные данные в файл так быстро, как это происходит.Я немного новичок в темах, поэтому я не уверен, что делать, чтобы избавиться от этого состояния гонки.Есть намеки?

1 Ответ

3 голосов
/ 10 января 2012

это классический потребитель / производитель.самый простой / простой способ справиться с этим - использовать BlockingQueue.производитель звонит put(), потребитель звонит take().

примечание, использование BlockingQueue обычно приводит к проблеме "как закончить".лучший способ сделать это - использовать метод «ядовитой пилюли», когда производитель помещает «специальное» значение в очередь, которое сигнализирует потребителю, что данных больше нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...