Задача на многопоточность.

 
 
 
Сообщения:7
Задача:

Необходимо реализовать многопоточное приложение, которое решает следующую задачу:
Есть два типа пользователя (два типа потока). Один - Хозяин, имеет в своем арсенале список вещей (Вещь: цена и вес), второй - Вор, имеет рюкзак (Рюкзак: предельный вес, который может в себя вместить). Поток Хозяина выполняет работу по выкладыванию вещей в квартиру. Поток Вора - забирает вещи из квартиры. При этом Вор должен забрать такие вещи, чтобы их ценность была максимальной и вес их должен быть меньше предельного веса, который может поместиться в рюкзак.

Объектные модели:
1. Вещь; атрибуты: вес, ценность
2. Хозяин; атрибуты: Вещи; действия: внести вещи в квартиру
3. Рюкзак; атрибуты: предельный вес
3. Вор; атрибуты: рюкзак. Действия: сложить вещи в рюкзак.

Ограничения:
1. Если работает поток Хозяина, то вор не должен класть вещи в рюкзак.
2. Если работает Вор, то Хозяин не может войти в квартиру

Возможные ограничения системы:
1. Хозяев может быть 1..n.
2. потоки Хозяев БЕЗ взаимной блокировки: несколько хозяев могут выкладывать вещи в квартиру одновременно
3. Воров может быть 1..m.
4. Потоки Воров со ВЗАИМНОЙ блокировкой: воровать одновременно может только 1 вор."

Если я правильно понимаю у нас должен быть дом, куда хозяин будет складывать вещи и откуда забирать. Может кто-нибудь поможет разобраться?


public class Thing {
    private int weight;
    private int price;

    public Thing(int weight, int price) {
        this.weight = weight;
        this.price = price;
    }


    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }
}




public class Thief implements Runnable{
    Apartment apartment = new Apartment();
    private BackPack backPack;
    private Random random = new Random();

    public BackPack getBackPack() {
        return backPack;
    }

    public void setBackPack(BackPack backPack) {
        this.backPack = backPack;
    }

    public Thief(BackPack backPack) {
        this.backPack = backPack;
    }

    public void foldThings() {
        apartment.add(getBackPack().getThing());
         apartment.get();
        }

    public void run() {
        int i = 0;
        while (i < random.nextInt(8) + 1) {
            try {
                System.out.println("Вор зашел");
                foldThings();
                System.out.println("Вор вышел");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("Вор замер");
            }
        }
            i++;
    }
}




public class Owner implements Runnable{
    private Apartment apartment = new Apartment();
    private Thing thing;
    private Random random = new Random();

    public Owner(Thing thing) {
        this.thing = thing;

    }

    public Thing getThing() {
        return thing;
    }

    public void setThing(Thing thing) {
        this.thing = thing;
    }

    public void bringIn(){
        apartment.add(new Thing(random.nextInt(5)+1, random.nextInt(20000)+100));
    }

    public void run() {
        int i = 0;
            while (i<random.nextInt(8)+1)
            try {
                    System.out.println("Хозяин пришел");
                    bringIn();
                    System.out.println("Хоязин ушел");

                    Thread.sleep(1000);

            } catch (InterruptedException e) {
                System.out.println("Хоязин замер");
            }
            i++;
        }
    }




public class Apartment {
    Random random = new Random();
    ArrayList<Thing> things = new ArrayList<>();
    ArrayList<Owner> owners = new ArrayList<>();
    ArrayList<Thief> thieves = new ArrayList<>();
    ArrayList<BackPack> backPacks = new ArrayList<>();

    private int maxThievesInApartment = 5;
    private int thievesCounter = 0;
    private int maxOwnersInApartment = 8;
    private int ownerCounter = 0;
    private int maxThings = 10;
    private int thingsCounter = 0;



    public synchronized boolean add(Thing thing){
        try {
            if(thingsCounter < maxThings | ownerCounter < maxOwnersInApartment){
                notifyAll();
                things.add(thing);
                owners.add(new Owner(thing));
                System.out.println( owners.size() + " и принес " + things.size() + " вещи ценой " + thing.getPrice() + " и весом " + thing.getWeight() + " кг");
                thingsCounter++;
                ownerCounter++;
            }
            else {
                System.out.println("Все хозяева принесли вещи" );
                wait();
                return false;
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return true;
        }

    public synchronized BackPack get(Thing thing) {

        try {
            if (thievesCounter < maxThievesInApartment || thingsCounter > 0) {
                notifyAll();
                for (BackPack backPack:backPacks) {
                     {
                        backPacks.add(new BackPack(50, things.get()));
                        thingsCounter--;
                        System.out.println(things.size() + " вещей осталось дома");
                        things.remove(thing);
                        return backPack;
                    }
                }
            }

            System.out.println("Не осталось не одной вещи дома");
            wait();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }


    }



public class BackPack {
    private int maxWeight;
    private Thing thing;

    public BackPack(int maxWeight, Thing thing) {
        this.maxWeight = maxWeight;
        this.thing = thing;
        if (maxWeight < thing.getWeight()){
            System.out.println("Максимальный вес рюкзака превышен");
        }
    }

    public Thing getThing() {
        return thing;
    }

    public void setThing(Thing thing) {
        this.thing = thing;
    }

    public int getMaxWeight() {
        return maxWeight;
    }

    public void setMaxWeight(int maxWeight) {
        this.maxWeight = maxWeight;
    }
}




public class Main {

    public static void main(String[] args) throws InterruptedException {
        Random random = new Random();

        Owner owner = new Owner(new Thing(random.nextInt(10)+1, random.nextInt(20000)+100));
        Thread ownerThread = new Thread(owner);
        ownerThread.start();

        Thief thief = new Thief(new BackPack(random.nextInt(10)+1, owner.getThing()));
        Thread thiefThread = new Thread(thief);
        thiefThread.start();

    }

}
Изменен:17 апр 2019 06:48
 
 
Сообщения:564
Во вторых: Это тестовое задание? Если да, то забавно, пошутить решили наверное.
Во первых: Если хотите что бы вам помогли оформляйте сообщения правильно. В частности для исходного кода есть тег code (можно просто выделить исходный код и нажать кнопочку "Код"), иначе это нечитаемый набор буковок.
Изменен:16 апр 2019 15:52
 
 
Сообщения:7
izon:
Во вторых: Это тестовое задание? Если да, то забавно, пошутить решили наверное.
Во первых: Если хотите что бы вам помогли оформляйте сообщения правильно. В частности для исходного кода есть тег code (можно просто выделить исходный код и нажать кнопочку "Код"), иначе это нечитаемый набор буковок.


Ох, уж эти состоявшиеся программисты. Всё вы никак мимо не проходите. Если это тестовое задание, то что, стесняюсь спросить? Не стоит вашего внимания, так как его я должен выполнить сам? А если я для себя решаю, то можно? Собственно, что с вами не так? Вроде образованные люди, откуда высокомерие в вас? Неправильно оформил, хорошо, простите, учту. Касательно, вопроса. Он не заключался в том, чтобы вы отгадали шутка это или нет. С чего вам в голову приходит мысль, что можете спокойно высказывать свое мнение в интернете? Это вроде форум для глупых вопросов. Вот я и задал свой глупый вопрос. Или вы заходите для горчинки сюда? Или чтобы самоутвердиться? Вопросы риторические.
 
 
Сообщения:564
GSH:
Неправильно оформил, хорошо, простите, учту.

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

Я имел в виду что пошутил тот кто дал вам такое задание.
GSH:
Решена

Не верю.
Хотя если вы сумели решить NP-полную задачу, то мои поздравления.
 
 
Сообщения:7
Quote:
Не верю.
Хотя если вы сумели решить NP-полную задачу, то мои поздравления.


Вас не проведешь. Просто появились мысли, как это сделать. Если зайду в тупик, то вновь обращусь, уже с учетом предыдущих ошибок.

Quote:
Я имел в виду что пошутил тот кто дал вам такое задание.


Она не решаема? Мой недостаток опыта в решении подобных задач остается лишь моей проблемой. Как по мне, задача интересная. Нужно просто понять от чего отталкиваться хотя бы. Я задал вопрос исключительно ради того, чтобы кто-нибудь подсказал правильно ли я мыслю и в каком направлении мне двигаться дальше.
 
 
Сообщения:1641
Quote:
выкладыванию вещей в квартиру. Поток Вора - забирает вещи из квартиры

Должен быть ещё объект квартира.
И В рюкзаке должна быть не 1 вещь, а список вещей.

Насчет задачи непонятно.
Пусть рюкзак с допустимым весом 10.
В квартире появилась вещь с весом 6, ее забрали. Рюкзак имеет 6/10
Тут выложили 2 вещи по 5кг. То есть теперь оптимально 2 вещи по 5.
Можно ли узнать весь список вещей, которые есть в квартире? Что делать со старой вещью с весом 6?

Если сделать несколько допущений, то думаю должно быть следующим образом.

Класс квартира имеет List вещей которые в ней лежат

Когда вор начинает работу с квартирой, то нужно блокировать весь объект, например с помощью Lock
- далее получаем весь список в квартире
- смотрим какие объекты есть в рюкзаке
- решаем классическую "задачу о рюкзаке"
- ненужные вещи из рюкзака складываем в квартиру
- отпускаем Lock
- печатаем новые вещи в рюкзаке

Хозяин же просто лочит объект и кладет вещь со случайным весом и стоимостью, стоит учесть удаление вещей из квартиры иначе очередь будет бесконечно расти.
 
 
Сообщения:7
Quote:
Класс квартира имеет List вещей которые в ней лежат

А информацию о ворах и хозяевах она тоже содержит? А списку вещей в рюкзаке мы передаем список вещей, которые в квартире?
 
 
Сообщения:1641
Нет, квартире нет надобности знать пользователей. У нее есть только 3 интерфейса с внешним миром
- получить список всех вещей(это нужно для того чтобы вор понял чем набить свой рюкзак)
- взять определенную вещь(после того как вор посчитает как ему сложить вещи в рюкзак)
- положить вещь(для хозяина и вора, чтобы выложить лишние вещи)
Ну и наверно все же стоит методы заблокировать/разблокировать дом, чтобы вор и владелец не пересекались

Quote:
А списку вещей в рюкзаке мы передаем список вещей, которые в квартире?

Не которые в квартире, а которые нужно хранить на очередном шаге
Например там была 1 вещь со стоимостью 6
Вор на очередном шаге увидел, что в доме 2 вещи со стоимостью 5
Он посчитал что 5 + 5 = 10 и это лучше чем 6
Он очистил рюкзак и положил в него 2 пятерки и заснул до следующей проверки
 
 
Сообщения:7
Получить список - я реализовал через геттер, положить вещь и взять - 2 метода с параметром вещь. У одного тип хозяин, у второго вор. Я предполагал, что один будет добавлять в список, а второй из него доставать.

Owner addThingInApartment(Thing thing)


Thief removeThingInApartment(Thing thing)


При этом, проблема такого решения заключается в том, что когда я в классы Thief и Owner передаю эти методы, я создаю новые вещи. Как можно это решить? Может remove без параметра?
То есть для большей наглядности пишу, следующим образом


 public void foldThings() {

            apartment.removeThingInApartment(new Thing(random.nextInt(10)+1, random.nextInt(4000)+100));
        }
    
    public void run() {
            try {
                System.out.println("Вор зашел");
                foldThings();
                System.out.println("Вор вышел");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("Вор замер");
            }


 public void bringIn(){
        apartment.addThingInApartment(new Thing(random.nextInt(10)+1, random.nextInt(4000)+100));
    }

    public void run() {

            try {
                 {
                    System.out.println("Хозяин пришел");
                    bringIn();
                    System.out.println("Хоязин ушел");

                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                System.out.println("Хоязин замер");
            }
        }
 
 
Сообщения:1641
Thief и Owner не стоит делать Runnable
Сделайте отдельные классы
ThiefTask и OwnerTask
Создайте дом, владельца и вора
Создайте ThiefTask и OwnerTask, в первый класс поместите дом + вор, во второй тот же самый дом + владелец

Quote:
- 2 метода с параметром вещь

Берете список всех вещей, ищите среди неё ту что нужна, вытаскиваете ее
 
 
Сообщения:7
Quote:
Thief и Owner не стоит делать Runnable
Сделайте отдельные классы
ThiefTask и OwnerTask
Создайте дом, владельца и вора
Создайте ThiefTask и OwnerTask, в первый класс поместите дом + вор, во второй тот же самый дом + владелец


А класс рюкзак и вещь, тоже создаем? Все методы в классе дом должны быть синхронизированные, верно? Какой им тип задать, чтобы я их в дальнейшем использовал и в классе хозяев и в классе воров? Сижу 3 день над задачей. Может есть какие-то ресурсы с задачами подобного плана и с решением?


Quote:
Ну и наверно все же стоит методы заблокировать/разблокировать дом, чтобы вор и владелец не пересекались


Данные методы надо сделать boolean? И включить их в методы которые добавляют и получают список?
Изменен:18 апр 2019 09:24
 
 
Сообщения:1641
Quote:
А класс рюкзак и вещь, тоже создаем?

Да. В ООП реальные предметы из мира лучше представлять их классами

Quote:
Все методы в классе дом должны быть синхронизированные, верно?

Нет, синхонизация объектов блокирует объект для других потоков. Но нам надо заблокироваться надолго, так как надо сделать 3 вещи. Получить список вещей, посчитать каки вещи нужны, выложить вещи обратно. И в это время дом должен быть недоступен. Так что используйте Lock
То есть в доме сделайте объект класса Lock и 2 метода lock unlock(прочитайте про него в интернете)

Quote:
Сижу 3 день над задачей

Не самая удачная задача, для начала обучения многопоточности

Quote:
Может есть какие-то ресурсы с задачами подобного плана и с решением?

Я обучался на работе, ресурсов не знаю. Лучше смотреть уроки по многопоточности и самому решать придумывать задачи.

Quote:
Данные методы надо сделать boolean?

void. Главная идея метода lock, что он не дает пройти дальше, если кто-то уже сделал lock

Quote:
И включить их в методы которые добавляют и получают список?

Нет, их вынести отдельно. Хочешь положить вещь? Сделай lock, положи вещь, сделай unlock
Хочешь украсть вещи? Сделай lock, Сделай все что надо, сделай unlock
 
 
Сообщения:7
Спасибо вам, большое.


Quote:
Не самая удачная задача, для начала обучения многопоточности


Взяли на стажировку, в процессе которой, один из пунктов изучение многопоточности. Тим лид дал задачу.
Изменен:18 апр 2019 19:22
 
Модераторы:frymock
Сейчас эту тему просматривают:Нет