Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Задача производитель-потребитель 
:(
    Опции темы
Loginanton
Дата 2.11.2010, 13:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 114
Регистрация: 8.11.2007

Репутация: нет
Всего: нет



Добрый день. Помогите пожалуйста сделать лабу в универ. Конкретно неполучается сделать следующее: есть следующий класс:
Код

class Buffer
{
 int data;
 void push(int a)
 {
  data = a;
 }
 int pop()
 {
  return data;
 }
}

Требуется сделать цикл (100 итераций) в котором один поток (я его назвал Writer) записывает в класс Buffer рандомное число от 1 до 9 и засыпает (Thread.sleep()) на такое число секунд, а другой поток (его я обозвал Reader) читает число из класса Buffer и к примеру выводит на экран. Т.е. должно быть так: Writer записывает в Buffer число, к примеру 4 и засыпает на 4 сек; пока Writer спит Reader должен прочесть из Buffer число и вывести его, а дальше ждать пока Writer снова не запишет в Buffer число, ну и т.д. Для синхронизации потоков (Writer и Reader) нужно использовать synchronized, wait(), notify(); а проверять пуст ли Buffer нельзя. Вот с синхронизацией и проблемы, пока никак победить немогу. Заранее благодарен за помощь.
PM   Вверх
mantracoder
Дата 2.11.2010, 14:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 3.8.2007

Репутация: 1
Всего: 1



Не вижу в приведенном коде даже попытки сделать синхронизацию. 
PM MAIL   Вверх
Loginanton
Дата 2.11.2010, 14:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 114
Регистрация: 8.11.2007

Репутация: нет
Всего: нет



Вот код, который на данный момент:
Код

import java.util.*;

class Writer implements Runnable
{
    Buffer b;
    Writer(Buffer b)
    {
        this.b = b;
        Thread t = new Thread(this);
        t.start();
    }
    public void run()
    {
        Random r = new Random();
        int data;
        for(int i = 0; i < 100; i++)
        {
            data = r.nextInt(9);
            data++;
            b.setData(data);
            
            try
            {
                Thread.sleep(data*1000);
            }
            catch(InterruptedException e)
            {
                ;
            }
            
        }
    }
}

class Reader extends Thread
{
    Buffer b;
    Reader(Buffer b)
    {
        this.b = b;
        start();
    }
    public void run()
    {
        for(int i = 0; i < 100; i++)
        {
            System.out.println(i+ ": " + b.getData());
        }
    }
}

class Buffer
{
    int data;
    synchronized int getData()
    {

        int result = this.data;
        notify();
        try{ wait(); } catch (InterruptedException e) { ; }
        return result;
    }
    synchronized void setData(int data)
    {

        this.data = data;
        notify();
        try{ wait(); } catch (InterruptedException e) { ; }
    }
}

class java_5
{
    static public void main(String[] args)
    {
        Buffer b = new Buffer();
        new Writer(b);
            try
            {
                Thread.sleep(2);
            }
            catch(InterruptedException e)
            {
                ;
            }
        new Reader(b);
    }
}

PM   Вверх
mantracoder
Дата 2.11.2010, 15:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 3.8.2007

Репутация: 1
Всего: 1




Код

public class Sample {

    public static void main(String[] args) {
        Buffer buffer = new Buffer();
        int iterations = 100;
        
        new Writer(buffer, iterations).start();
        new Reader(buffer, iterations).start();
    }

}


Код

public class Buffer {

    private List<Integer> store = new ArrayList<Integer>();
    
    public void push(Integer data) {
        synchronized (store) {
            store.add(data);
            store.notify();
        }
    }
    
    public Integer pop() {
        synchronized (store) {
            if (store.isEmpty()) {
                try {
                    store.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return store.remove(0);
        }
    }
    
}


Код

public class Writer extends Thread {

    private static final int MAX_RANDOM = 9;
    
    private Buffer buffer;
    
    private int iterations;
    
    public Writer(Buffer buffer, int iterations) {
        this.buffer = buffer;
        this.iterations = iterations;
    }
    
    @Override
    public void run() {
        Random random = new Random(System.currentTimeMillis());
        for (int i=0; i<iterations; i++) {
            int data = random.nextInt(MAX_RANDOM) + 1;
            System.out.println("Writer is going to write " + data);
            buffer.push(data);
            try {
                sleep(data * 1000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}


Код

public class Reader extends Thread {

    private Buffer buffer;
    
    private int iterations;
    
    public Reader(Buffer buffer, int iterations) {
        this.buffer = buffer;
        this.iterations = iterations;
    }
    
    @Override
    public void run() {
        for (int i=0; i<iterations; i++) {
            int data = buffer.pop();
            System.out.println("Reader has read " + data);
        }
    }

}

PM MAIL   Вверх
Loginanton
Дата 2.11.2010, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 114
Регистрация: 8.11.2007

Репутация: нет
Всего: нет



mantracoder, это немного не то. Во первых данные в Buffer должны хранится в простом типе данных, а не в List. Во вторых нельзя проверять записано что то в Buffer или нет.
PM   Вверх
mantracoder
Дата 2.11.2010, 15:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 3.8.2007

Репутация: 1
Всего: 1



Цитата(Loginanton @ 2.11.2010,  15:25)
mantracoder, это немного не то. Во первых данные в Buffer должны хранится в простом типе данных, а не в List. Во вторых нельзя проверять записано что то в Buffer или нет.

1) Если значение буфера будет хранится в простом типе, то что произойдет, если Writer успеет записать в буфер более 1 значения, прежде чем Reader соизволит прочитаеть?

2) Reader не проверяет, есть ли значение в буфере. Проверяет сам Buffer, в противном случае, как вы определите, что поток должен ждать?

Сообственно, пример у вас есть, допиливайте его по своему усмотрению.
PM MAIL   Вверх
nc30
Дата 2.11.2010, 17:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Интересующийся :)
*


Профиль
Группа: Участник
Сообщений: 140
Регистрация: 24.6.2010
Где: Санкт-Петербург

Репутация: 5
Всего: 8



Loginanton,
Код

public class Buffer {

    public static final int COUNT = 100;
    
    private int content;
    private boolean available = false;

    public synchronized int read() {
        while (available == false) {
            try {
                System.out.println("[Buffer]: waiting for write...");
                wait();
            } catch (InterruptedException e) {
            }
        }
        available = false;
        System.out.println("[Buffer]: " + content + " was read from buffer");
        notifyAll();
        return content;
    }

    public synchronized void write(int value) {
        while (available == true) {
            try {
                System.out.println("[Buffer]: waiting for read...");
                wait();
            } catch (InterruptedException e) {
            }
        }
        content = value;
        available = true;
        System.out.println("[Buffer]: " + value + " was written to buffer");
        notifyAll();
    }
}

Код

public class Writer extends Thread {

    private Buffer buffer;

    public Writer(Buffer buffer) {
        this.buffer = buffer;
    }

    @Override
    public void run() {
        for (int i = 0; i < Buffer.COUNT; i++) {
            int sec = (int) Math.round(Math.random() * 9);
            System.out.println("[Writer]: trying to write " + sec + "...");
            buffer.write(sec);
            try {
                System.out.println("[Writer]: go to sleep (" + sec + " sec.)" );
                Thread.sleep(sec*1000);
            } catch (InterruptedException e) {
            }
        }
    }
}

Код

public class Reader extends Thread {

    private Buffer buffer;

    public Reader(Buffer buffer) {
        this.buffer = buffer;
    }

    @Override
    public void run() {
        for (int i = 0; i < Buffer.COUNT; i++) {
            System.out.println("[Reader]: trying to read...");
            buffer.read();
        }
    }
}

Код

public class Main {

    public static void main(String[] args) {
        Buffer b = new Buffer();
        Writer w = new Writer(b);
        Reader r = new Reader(b);
        
        r.start();
        w.start();
    }
}

Синхронизация всех действий происходит в объекте Buffer. Переменная available - для предотвращения дедлока.

P.S. Автор кода AntonSaburov + я подогнал немного под задачу.

Это сообщение отредактировал(а) nc30 - 2.11.2010, 17:16
PM MAIL   Вверх
Loginanton
Дата 2.11.2010, 17:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 114
Регистрация: 8.11.2007

Репутация: нет
Всего: нет



Нужно чтобы Reader и Writer работали поочереди, как бы передавая друг другу эстафетную палочку - вот этого я лично никак добиться немогу.
PM   Вверх
nc30
Дата 2.11.2010, 18:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Интересующийся :)
*


Профиль
Группа: Участник
Сообщений: 140
Регистрация: 24.6.2010
Где: Санкт-Петербург

Репутация: 5
Всего: 8



Loginanton,
Они и так работают поочереди. Buffer лишь обеспечивает хранение полезного значения и безопасный доступ к нему. Не поленитесь скомпилировать код и посмотреть на результаты его работы: там все прозрачно.

Не очень понимаю, что вас конкретно не устраивает. Не нравятся методы в Buffer? Они спроектированы с учетом защиты от deadlock. Считайте их потокобезопасными сетером и гетером для хранящегося там полезного значения. Если вы переместите эти методы в потоковые классы и откроете доступ к хранящемуся в буфере значению, то ни о какой потокобезопасности говорить не придется.

Смущает обилие вывода на консоль объектом класса Buffer? Это сделано для того, чтобы вы понимали суть происходящих в программе нелинейных процессов. Разобравшись, вы можете безболезненно удалить ненужные вам вызовы println(), оставив чистую функциональность (хотя в этом случае пример потеряет в наглядности).

Удачи  smile 

Это сообщение отредактировал(а) nc30 - 3.11.2010, 05:47
PM MAIL   Вверх
alexsaltykov
Дата 3.11.2010, 09:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 17.8.2007

Репутация: нет
Всего: нет



Внесу свои 5 копеек
У меня без deadlock попроще конечно, но вроде работает.

Код

import java.util.Random;

public class Main{

    private static final int MAX_RANDOM = 9;
    public volatile int bufer;   

    /**
     * @param args
     */
    public static void main(String[] args) {
        Bufer bufer=new Bufer();
        Reader read=new Reader(bufer);
        Writer writer=new Writer(bufer);

        read.start();
        writer.start();                        
    }    
}



Код


public class Reader extends Thread {    
    public Bufer buf;

    
    public Reader(Bufer buffer){
     buf=buffer;     
    }
      
    @Override
    public void run() {     
        while (true){
            try {
                buf.read();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}


Код

public class Bufer {

    private volatile int bufer;

    public synchronized int read() throws InterruptedException {        
        System.out.println("[Buffer]: reading "+bufer);
        wait();
        return bufer;
    }

    public synchronized void write(int bufer) throws InterruptedException {
        System.out.println("[Buffer]: write "+bufer);
        this.bufer = bufer;        
        this.notifyAll();
        wait(bufer*1000);        
    }        
}


Код

import java.util.Random;


public class Writer extends Thread{
    
    private static final int MAX_RANDOM = 4;
    public Bufer buf;
    public Reader wr;

    public Writer(Bufer buffer){
        buf=buffer;    
    }
    
    
     @Override
     public void run() {
         Random random = new Random(System.currentTimeMillis());
         for(int i=0;i<100;i++){
                int data=random.nextInt(MAX_RANDOM) + 1;                                
                try {
                    buf.write(data);                                    
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                
            }
     }
}

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0831 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.