Advertisement
JovanPapi

[OS - lab3] Задача 3 - Tribe Member's Dinner

Apr 1st, 2019
272
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 14.49 KB | None | 0 0
  1. Задача 3
  2. Едно племе јаде заеднична вечера од голем котел во кој има ограничен број порции. Секој член од племето сам се послужува, доколку има храна во казанот. Доколку казанот е празен, се повикува готвачот за да зготви нов казан со храна. Притоа, само еден член може да прави провекра на тоа дали има храна во казанот во одреден момент и околу казанот има место за максимум тројца, што значи дека максимум тројца истовремено може да земаат храна, но бројот на членови кои јадат паралелно не е ограничен.
  3.  
  4. Казанот е иницијално празен.
  5.  
  6. Вашата задача е да го синхронизирате претходното сценарио.
  7.  
  8. Во почетниот код кој е даден, дефинирана е класата TribeMember, која го симболизира однесувањето на членовите на племето. Има повеќе инстанци од класата TribeMember кај кои методот execute() се повикува повеќе пати.
  9.  
  10. Во имплементацијата, можете да ги користите следните методи од веќе дефинираната променлива state:
  11.  
  12. state.isPotEmpty()
  13. Служи за проверка дали има храна во казанот. Овој метод манипулира со глобални променливи и треба да е во критичен регион.
  14. Доколку повеќе членови паралелно проверуваат, повикот ќе фрли исклучок.
  15. state.fillPlate()
  16. Го симболизира земањето на храна од казанот.
  17. Доколку казанот е празен или повеќе од тројца паралелно земаат храна од казанот, повикот ќе фрли исклучок.
  18. state.eat()
  19. Го симболизира конзумирањето на храната од страна на членовите на племето.
  20. state.cook()
  21. Го симболизира готвењето на храна во казанот од страна на готвачот.
  22. Доколку казанот не е празен, овој повик ќе фрли исклучок.
  23. Претходно назначените методи служат за проверка на точноста на сценариото и не смеат да бидат променети и мораат да бидат повикани.
  24.  
  25. Вашата задача е да ги имплементирате методите TribeMember.execute() и init(). При имплементацијата, не смеете да додадете try-catch блок во нив. Потребните семафори, глобални променливи и променливи за состојбите на берберо ти клиентот треба да ги дефинирате самите.
  26.  
  27. Доколку имате грешка, ќе ја добиете пораката:
  28.  
  29. Procesot ne e sinhroniziran spored uslovite na zadacata
  30.  
  31. По што ќе ви се прикаже логот на повикување на акциите и настанатите грешки. Овој лог треба да ви послужи за увидување на тоа каде имате грешка во извршувањето на вашата задача.
  32.  
  33.  
  34.  
  35. package Zadaca3;
  36.  
  37. import java.util.ArrayList;
  38. import java.util.HashMap;
  39. import java.util.HashSet;
  40. import java.util.List;
  41. import java.util.Map;
  42. import java.util.Random;
  43. import java.util.Scanner;
  44. import java.util.concurrent.Semaphore;
  45. import java.util.concurrent.atomic.AtomicInteger;
  46.  
  47. /**
  48.  *
  49.  * @author ristes
  50.  */
  51. public class TribeDinner {
  52.  
  53.     // TODO: definirajte gi semaforite i ostanatite promenlivi ovde (mora site
  54.     // da se static)
  55.     static Semaphore maxPlateTakers;
  56.     static Semaphore canCheck;
  57.     /**
  58.      * Metod koj treba da gi inicijalizira vrednostite na semaforite i
  59.      * ostanatite promenlivi za sinhronizacija.
  60.      *
  61.      *
  62.      * TODO: da se implementira
  63.      *
  64.      */
  65.     public static void init(int numBarbers) {
  66.         canCheck = new Semaphore(1);
  67.         maxPlateTakers = new Semaphore(3);
  68.  
  69.     }
  70.  
  71.     static class TribeMember extends TemplateThread {
  72.  
  73.         public TribeMember(int numRuns) {
  74.             super(numRuns);
  75.         }
  76.  
  77.         /**
  78.          * Da se implementira odnesuvanjeto na ucesnikot spored uslovite na
  79.          * zadacata.
  80.          */
  81.         public void execute() throws InterruptedException {
  82.             // nesinhronizirano scenario
  83.             canCheck.acquire();
  84.             if (!state.isPotEmpty()) {
  85.                 canCheck.release();
  86.                 maxPlateTakers.acquire();
  87.                 state.fillPlate();
  88.                 maxPlateTakers.release();
  89.                
  90.                 state.eat();
  91.             } else {
  92.                 canCheck.release();
  93.                 state.cook();
  94.             }
  95.  
  96.         }
  97.     }
  98.  
  99.     // <editor-fold defaultstate="collapsed" desc="This is the template code" >
  100.     static State state;
  101.  
  102.     static class State {
  103.  
  104.         private static final String _10_JADENJETO_NE_E_PARALELIZIRANO = "jadenjeto ne e paralelizirano. Site jadat eden po eden";
  105.         private static final String _10_PRISTAPOT_DO_KAZANOT_NE_E_PARALELIZIRAN = "Pristapot do kazanot ne e paraleliziran. Treda da moze do trojca paralelno da zemaat hrana.";
  106.  
  107.         private static final String _10_DVAJCA_ISTOVREMENO_PROVERUVAAT = "Dvajca istovremeno proveruvaat dali kazanot e prazen. Maksimum eden e dozvoleno.";
  108.         private static final String _7_NEMA_MESTO_POKRAJ_KAZANOT = "Nema mesto pokraj kazanot. Maksimum tri clena moze da zemaat hrana istovremeno.";
  109.         private static final String _5_NE_MOZE_DA_JADE_OD_PRAZEN_KAZAN = "Ne moze da jade od prazen kazan. Treba da se povika 'state.cook()'";
  110.         private static final String _5_NE_MOZE_DA_SE_GOTVI_VO_KAZAN_KOJ_NE_E_PRAZEN = "Ne moze da se gotvi vo kazan koj ne e prazen";
  111.  
  112.         private static final Random RANDOM = new Random();
  113.         private static final int POT_CAPACITY = 15;
  114.  
  115.         private LimitedCounter platesLeft = new LimitedCounter(0, null, 0,
  116.                 null, 0, 5, _5_NE_MOZE_DA_JADE_OD_PRAZEN_KAZAN);
  117.  
  118.         private LimitedCounter checks = new LimitedCounter(0, 1, 10,
  119.                 _10_DVAJCA_ISTOVREMENO_PROVERUVAAT, null, 0, null);
  120.  
  121.         private LimitedCounter fills = new LimitedCounter(0, 3, 7,
  122.                 _7_NEMA_MESTO_POKRAJ_KAZANOT, null, 0, null);
  123.  
  124.         private LimitedCounter eat = new LimitedCounter(0);
  125.  
  126.         public State() {
  127.  
  128.         }
  129.  
  130.         public boolean isPotEmpty() throws RuntimeException {
  131.             log(checks.incrementWithMax(), "proverka dali ima hrana vo kazanot");
  132.             sleep(5);
  133.             boolean res = platesLeft.getValue() == 0;
  134.             log(checks.decrementWithMin(), null);
  135.             return res;
  136.         }
  137.  
  138.         public void fillPlate() throws RuntimeException {
  139.             log(fills.incrementWithMax(), "zemanje na hrana");
  140.             log(platesLeft.decrementWithMin(), null);
  141.             sleep(5);
  142.             log(platesLeft.incrementWithMax(), null);
  143.             log(fills.decrementWithMin(), null);
  144.         }
  145.  
  146.         public void eat() throws RuntimeException {
  147.             log(eat.incrementWithMax(), "jadenje");
  148.             sleep(10);
  149.             log(eat.decrementWithMin(), null);
  150.         }
  151.  
  152.         public void cook() throws RuntimeException {
  153.             synchronized (State.class) {
  154.                 if (platesLeft.getValue() == 0) {
  155.                     platesLeft.setValue(POT_CAPACITY);
  156.                 } else {
  157.                     PointsException e = new PointsException(5,
  158.                             _5_NE_MOZE_DA_SE_GOTVI_VO_KAZAN_KOJ_NE_E_PRAZEN);
  159.                     log(e, null);
  160.                 }
  161.             }
  162.         }
  163.  
  164.         public void finalize() {
  165.             if (fills.getMax() == 1) {
  166.                 logException(new PointsException(10,
  167.                         _10_PRISTAPOT_DO_KAZANOT_NE_E_PARALELIZIRAN));
  168.             }
  169.             if (eat.getMax() == 1) {
  170.                 logException(new PointsException(10,
  171.                         _10_JADENJETO_NE_E_PARALELIZIRANO));
  172.             }
  173.         }
  174.  
  175.         private List<String> actions = new ArrayList<String>();
  176.  
  177.         private void sleep(int range) {
  178.             try {
  179.                 Thread.sleep(RANDOM.nextInt(range));
  180.             } catch (InterruptedException e) {
  181.             }
  182.         }
  183.  
  184.         protected TemplateThread getThread() {
  185.             TemplateThread t = (TemplateThread) Thread.currentThread();
  186.             return t;
  187.         }
  188.  
  189.         private synchronized void log(PointsException e, String action) {
  190.             TemplateThread t = (TemplateThread) Thread.currentThread();
  191.             if (e != null) {
  192.                 t.setException(e);
  193.                 actions.add(t.toString() + "\t(e): " + e.getMessage());
  194.             } else if (action != null) {
  195.                 actions.add(t.toString() + "\t(a): " + action);
  196.             }
  197.         }
  198.  
  199.         private synchronized void logException(PointsException e) {
  200.             actions.add("\t(e): " + e.getMessage());
  201.         }
  202.  
  203.         public synchronized void printLog() {
  204.             System.out
  205.                     .println("Poradi konkurentnosta za pristap za pecatenje, mozno e nekoja od porakite da ne e na soodvetnoto mesto.");
  206.             System.out.println("Log na izvrsuvanje na akciite:");
  207.             System.out.println("=========================");
  208.             System.out.println("tip\tid\titer\takcija/error");
  209.             System.out.println("=========================");
  210.             for (String l : actions) {
  211.                 System.out.println(l);
  212.             }
  213.         }
  214.  
  215.         public void printStatus() {
  216.             finalize();
  217.             if (!TemplateThread.hasException) {
  218.                 int poeni = 25;
  219.                 if (PointsException.getTotalPoints() == 0) {
  220.                     System.out
  221.                             .println("Procesot e uspesno sinhroniziran. Osvoeni 25 poeni.");
  222.                 } else {
  223.                     poeni -= PointsException.getTotalPoints();
  224.                     PointsException.printErrors();
  225.                     System.out.println("Maksimalni osvoeni poeni: " + poeni);
  226.                 }
  227.  
  228.             } else {
  229.                 System.out
  230.                         .println("Procesot ne e sinhroniziran spored uslovite na zadacata");
  231.                 printLog();
  232.                 System.out
  233.                         .println("====================================================");
  234.                 PointsException.printErrors();
  235.                 int total = (25 - PointsException.getTotalPoints());
  236.                 if (total < 0) {
  237.                     total = 0;
  238.                 }
  239.                 System.out.println("Maksimum Poeni: " + total);
  240.             }
  241.  
  242.         }
  243.     }
  244.  
  245.     static class LimitedCounter {
  246.  
  247.         private int value;
  248.         private Integer maxAllowed;
  249.         private Integer minAllowed;
  250.         private int maxErrorPoints;
  251.         private int minErrorPoints;
  252.         private String maxErrorMessage;
  253.         private String minErrorMessage;
  254.  
  255.         private int max;
  256.  
  257.         public LimitedCounter(int value) {
  258.             super();
  259.             this.value = value;
  260.             this.max = value;
  261.         }
  262.  
  263.         public LimitedCounter(int value, Integer maxAllowed,
  264.                 int maxErrorPoints, String maxErrorMessage, Integer minAllowed,
  265.                 int minErrorPoints, String minErrorMessage) {
  266.             super();
  267.             this.value = value;
  268.             this.max = value;
  269.             this.maxAllowed = maxAllowed;
  270.             this.minAllowed = minAllowed;
  271.             this.maxErrorPoints = maxErrorPoints;
  272.             this.minErrorPoints = minErrorPoints;
  273.             this.maxErrorMessage = maxErrorMessage;
  274.             this.minErrorMessage = minErrorMessage;
  275.         }
  276.  
  277.         public int getMax() {
  278.             return max;
  279.         }
  280.  
  281.         public int getValue() {
  282.             return value;
  283.         }
  284.  
  285.         public void setValue(int value) {
  286.             this.value = value;
  287.         }
  288.  
  289.         public PointsException incrementWithMax() {
  290.             synchronized (LimitedCounter.class) {
  291.                 value++;
  292.                 if (value > max) {
  293.                     max = value;
  294.                 }
  295.                 if (maxAllowed != null) {
  296.                     if (value > maxAllowed) {
  297.                         PointsException e = new PointsException(maxErrorPoints,
  298.                                 maxErrorMessage);
  299.                         return e;
  300.                     }
  301.                 }
  302.             }
  303.             return null;
  304.         }
  305.  
  306.         public PointsException decrementWithMin() {
  307.             synchronized (LimitedCounter.class) {
  308.                 value--;
  309.                 if (minAllowed != null) {
  310.                     if (value < minAllowed) {
  311.                         PointsException e = new PointsException(minErrorPoints,
  312.                                 minErrorMessage);
  313.                         return e;
  314.                     }
  315.                 }
  316.             }
  317.             return null;
  318.         }
  319.     }
  320.  
  321.     abstract static class TemplateThread extends Thread {
  322.  
  323.         static boolean hasException = false;
  324.         int numRuns = 1;
  325.         public int iteration = 0;
  326.         protected Exception exception = null;
  327.  
  328.         public TemplateThread(int numRuns) {
  329.             this.numRuns = numRuns;
  330.         }
  331.  
  332.         abstract void execute() throws InterruptedException;
  333.  
  334.         @Override
  335.         public void run() {
  336.             try {
  337.                 for (int i = 0; i < numRuns && !hasException; i++) {
  338.                     execute();
  339.                     iteration++;
  340.  
  341.                 }
  342.             } catch (InterruptedException e) {
  343.                 // Do nothing
  344.             } catch (Exception e) {
  345.                 exception = e;
  346.                 hasException = true;
  347.             }
  348.         }
  349.  
  350.         public void setException(Exception exception) {
  351.             this.exception = exception;
  352.             hasException = true;
  353.         }
  354.  
  355.         @Override
  356.         public String toString() {
  357.             Thread current = Thread.currentThread();
  358.             if (numRuns > 1) {
  359.                 return String.format("%s\t%d\t%d", ""
  360.                         + current.getClass().getSimpleName().charAt(0),
  361.                         getId(), iteration);
  362.             } else {
  363.                 return String
  364.                         .format("%s\t%d\t", ""
  365.                                 + current.getClass().getSimpleName().charAt(0),
  366.                                 getId());
  367.             }
  368.         }
  369.     }
  370.  
  371.     static class PointsException extends RuntimeException {
  372.  
  373.         private static HashMap<String, PointsException> exceptions = new HashMap<String, PointsException>();
  374.         private int points;
  375.  
  376.         public PointsException(int points, String message) {
  377.             super(message);
  378.             this.points = points;
  379.             exceptions.put(message, this);
  380.         }
  381.  
  382.         public static int getTotalPoints() {
  383.             int sum = 0;
  384.             for (PointsException e : exceptions.values()) {
  385.                 sum += e.getPoints();
  386.             }
  387.             return sum;
  388.         }
  389.  
  390.         public static void printErrors() {
  391.             System.out.println("Gi imate slednite greski: ");
  392.             for (Map.Entry<String, PointsException> e : exceptions.entrySet()) {
  393.                 System.out.println(String.format("[%s] : (-%d)", e.getKey(), e
  394.                         .getValue().getPoints()));
  395.             }
  396.         }
  397.  
  398.         public int getPoints() {
  399.             return points;
  400.         }
  401.     }
  402.  
  403.     public static void main(String[] args) {
  404.         try {
  405.             start();
  406.         } catch (Exception ex) {
  407.             ex.printStackTrace();
  408.         }
  409.     }
  410.  
  411.     public static void start() throws Exception {
  412.         Scanner s = new Scanner(System.in);
  413.         int brKonzumeri = s.nextInt();
  414.         int numCustomerRuns = s.nextInt();
  415.         init(brKonzumeri);
  416.  
  417.         state = new State();
  418.         HashSet<Thread> threads = new HashSet<Thread>();
  419.  
  420.         for (int i = 0; i < brKonzumeri; i++) {
  421.             TribeMember c = new TribeMember(numCustomerRuns);
  422.             threads.add(c);
  423.             c.start();
  424.         }
  425.         try {
  426.             Thread.sleep(50);
  427.         } catch (Exception e) {
  428.             // do nothing
  429.         }
  430.  
  431.         for (Thread t : threads) {
  432.             t.join(1000);
  433.         }
  434.  
  435.         for (Thread t : threads) {
  436.             if (t.isAlive()) {
  437.                 t.interrupt();
  438.                 if (t instanceof TemplateThread) {
  439.                     TemplateThread tt = (TemplateThread) t;
  440.                     tt.setException(new PointsException(25, "DEADLOCK"));
  441.                 }
  442.             }
  443.         }
  444.         s.close();
  445.         state.printStatus();
  446.     }
  447.     // </editor-fold>
  448. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement