Advertisement
LonelyShepherd

Племенска вечера 2.0 [Лаб. 3.3.2]

Mar 20th, 2018
201
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 19.07 KB | None | 0 0
  1. import java.util.*;
  2. import java.util.concurrent.Semaphore;
  3.  
  4. public class SeptemberTribeDinner {
  5.     static Semaphore check, eat, cook, cooked;
  6.  
  7.     public static void init() {
  8.         check = new Semaphore(1);
  9.         eat = new Semaphore(4);
  10.         cook = new Semaphore(0);
  11.         cooked = new Semaphore(0);
  12.     }
  13.  
  14.     public static class TribeMember extends TemplateThread {
  15.  
  16.         public TribeMember(int numRuns) {
  17.             super(numRuns);
  18.         }
  19.  
  20.         @Override
  21.         public void execute() throws InterruptedException {
  22.             check.acquire();
  23.             if(state.isPotEmpty()) {
  24.                 cook.release();
  25.                 cooked.acquire();
  26.             }
  27.             state.fillPlate();
  28.             check.release();
  29.            
  30.             eat.acquire();
  31.             state.eat();
  32.             eat.release();
  33.         }
  34.     }
  35.  
  36.     public static class Chef extends TemplateThread {
  37.  
  38.         public Chef(int numRuns) {
  39.             super(numRuns);
  40.         }
  41.  
  42.         @Override
  43.         public void execute() throws InterruptedException {
  44.             cook.acquire();
  45.             state.cook();
  46.             cooked.release();
  47.                      
  48.         }
  49.  
  50.     }
  51.  
  52.     static SeptemberTribeDinnerState state = new SeptemberTribeDinnerState();
  53.  
  54.     public static void main(String[] args) {
  55.         for (int i = 0; i < 3; i++) {
  56.             run();
  57.         }
  58.     }
  59.  
  60.     public static void run() {
  61.         try {
  62.             int numRuns = 1;
  63.             int numIterations = 150;
  64.  
  65.             HashSet<Thread> threads = new HashSet<Thread>();
  66.  
  67.             for (int i = 0; i < numIterations; i++) {
  68.                 TribeMember h = new TribeMember(numRuns);
  69.                 threads.add(h);
  70.             }
  71.  
  72.             Chef chef = new Chef(10);
  73.             threads.add(chef);
  74.  
  75.             init();
  76.  
  77.             ProblemExecution.start(threads, state);
  78.             //System.out.println(new Date().getTime());
  79.         } catch (Exception ex) {
  80.             ex.printStackTrace();
  81.         }
  82.     }
  83. }
  84.  
  85.  
  86.  
  87. class SeptemberTribeDinnerState extends AbstractState {
  88.  
  89.     private static final int EMPTY_POT = 0;
  90.  
  91.     private static final String _10_JADENJETO_NE_E_PARALELIZIRANO = "jadenjeto ne e paralelizirano. Site jadat eden po eden";
  92.  
  93.     private static final String _10_DVAJCA_ISTOVREMENO_PROVERUVAAT = "Dvajca istovremeno proveruvaat dali kazanot e prazen. Maksimum eden e dozvoleno.";
  94.     private static final String _7_DVAJCA_ISTOVREMENO_POLNAT = "Dvajca istovremeno zemaat hrana od kazanot. Maksimum eden e dozvoleno.";
  95.     private static final String _5_NE_MOZE_DA_POLNI_OD_PRAZEN_KAZAN = "Ne moze da se polni od kazan. Treba da se povika 'state.cook()'";
  96.     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";
  97.     private static final String _7_NEMA_MESTO_NA_TRPEZATA = "Trpezata e polna. Nema mesto na trpezata za poveke od cetvorica. ";
  98.     private static final String _7_NEMA_ZEMENO_HRANA = "NEMA ZEMENO HRANA";
  99.     private static final String _7_POLNI_OD_PRAZEN_KAZAN = "POLNI OD PRAZEN KAZAN";
  100.  
  101.     private static final int POT_CAPACITY = 15;
  102.  
  103.     private BoundCounterWithRaceConditionCheck platesLeft = new BoundCounterWithRaceConditionCheck(
  104.             0, null, 0, null, 0, 10, _7_POLNI_OD_PRAZEN_KAZAN);
  105.  
  106.     private BoundCounterWithRaceConditionCheck checks = new BoundCounterWithRaceConditionCheck(
  107.             0, 1, 10, _10_DVAJCA_ISTOVREMENO_PROVERUVAAT, null, 0, null);
  108.  
  109.     private BoundCounterWithRaceConditionCheck fills = new BoundCounterWithRaceConditionCheck(
  110.             0, 1, 7, _7_DVAJCA_ISTOVREMENO_POLNAT, 0, 5,
  111.             _5_NE_MOZE_DA_POLNI_OD_PRAZEN_KAZAN);
  112.  
  113.     private BoundCounterWithRaceConditionCheck ready = new BoundCounterWithRaceConditionCheck(
  114.             0, null, 0, null, 0, 7, _7_NEMA_ZEMENO_HRANA);
  115.  
  116.     private BoundCounterWithRaceConditionCheck eat = new BoundCounterWithRaceConditionCheck(
  117.             0, 4, 7, _7_NEMA_MESTO_NA_TRPEZATA, null, 0, null);
  118.  
  119.     public SeptemberTribeDinnerState() {
  120.  
  121.     }
  122.  
  123.     /**
  124.      * Maksimum 1 proveruva.
  125.      *
  126.      * @return
  127.      * @throws RuntimeException
  128.      */
  129.     public boolean isPotEmpty() throws RuntimeException {
  130.         log(checks.incrementWithMax(), "proverka dali ima hrana vo kazanot");
  131.         boolean res = platesLeft.getValue() == 0;
  132.         log(checks.decrementWithMin(), null);
  133.         return res;
  134.     }
  135.  
  136.     /**
  137.      * Maksimum 1 zema paralelno. Ne smee da se povika od prazen kazan.
  138.      *
  139.      * @throws RuntimeException
  140.      */
  141.     public void fillPlate() throws RuntimeException {
  142.         log(fills.incrementWithMax(), "zemanje na hrana");
  143.         log(platesLeft.decrementWithMin(false), null);
  144.         log(fills.decrementWithMin(), null);
  145.         ready.incrementWithMax(false);
  146.     }
  147.  
  148.     /**
  149.      * Maksimum 4 jadat paralelno. Ne smeat da jadat eden po eden.
  150.      *
  151.      * @throws RuntimeException
  152.      */
  153.     public void eat() throws RuntimeException {
  154.         log(ready.decrementWithMin(false), null);
  155.         log(eat.incrementWithMax(false), "jadenje");
  156.         Switcher.forceSwitch(15);
  157.         log(eat.decrementWithMin(false), null);
  158.  
  159.     }
  160.  
  161.     /**
  162.      * Se povikuva od gotvacot. Ne smee da se povika koga kazanot ne e prazen.
  163.      *
  164.      * @throws RuntimeException
  165.      */
  166.     public void cook() throws RuntimeException {
  167.         log(platesLeft.assertEquals(EMPTY_POT, 5,
  168.                 _5_NE_MOZE_DA_SE_GOTVI_VO_KAZAN_KOJ_NE_E_PRAZEN), null);
  169.         Switcher.forceSwitch(10);
  170.         platesLeft.setValue(POT_CAPACITY);
  171.     }
  172.  
  173.     @Override
  174.     public void finalize() {
  175.         if (eat.getMax() == 1) {
  176.             logException(new PointsException(10,
  177.                     _10_JADENJETO_NE_E_PARALELIZIRANO));
  178.         }
  179.     }
  180.  
  181. }
  182. abstract class AbstractState {
  183.  
  184.     /**
  185.      * Method called after threads ended their execution to validate the
  186.      * correctness of the scenario
  187.      */
  188.     public abstract void finalize();
  189.  
  190.     /**
  191.      * List of logged actions
  192.      */
  193.     private List<String> actions = new ArrayList<String>();
  194.  
  195.     /**
  196.      *
  197.      * @return if the current thread is instance of TemplateThread it is
  198.      *         returned, and otherwise null is returned
  199.      */
  200.     protected TemplateThread getThread() {
  201.         Thread current = Thread.currentThread();
  202.         if (current instanceof TemplateThread) {
  203.             TemplateThread t = (TemplateThread) current;
  204.             return t;
  205.         } else {
  206.             return null;
  207.         }
  208.     }
  209.  
  210.     /**
  211.      * Log this exception or action
  212.      *
  213.      * @param e
  214.      *            occurred exception (null if no exception)
  215.      * @param action
  216.      *            Description of the occurring action
  217.      */
  218.     public synchronized void log(PointsException e, String action) {
  219.         TemplateThread t = (TemplateThread) Thread.currentThread();
  220.         if (e != null) {
  221.             t.setException(e);
  222.             actions.add(t.toString() + "\t(e): " + e.getMessage());
  223.             throw e;
  224.         } else if (action != null) {
  225.             actions.add(t.toString() + "\t(a): " + action);
  226.         }
  227.     }
  228.  
  229.     /**
  230.      * Logging exceptions
  231.      *
  232.      * @param e
  233.      */
  234.     protected synchronized void logException(PointsException e) {
  235.         Thread t = Thread.currentThread();
  236.         if (e != null) {
  237.             if (t instanceof TemplateThread) {
  238.                 ((TemplateThread) t).setException(e);
  239.             }
  240.             TemplateThread.hasException = true;
  241.             actions.add("\t(e): " + e.getMessage());
  242.             throw e;
  243.         }
  244.     }
  245.  
  246.     /**
  247.      * Printing of the actions and exceptions that has occurred
  248.      */
  249.     public synchronized void printLog() {
  250.         System.out
  251.                 .println("Poradi konkurentnosta za pristap za pecatenje, mozno e nekoja od porakite da ne e na soodvetnoto mesto.");
  252.         System.out.println("Log na izvrsuvanje na akciite:");
  253.         System.out.println("=========================");
  254.         System.out.println("tip\tid\titer\takcija/error");
  255.         System.out.println("=========================");
  256.         for (String l : actions) {
  257.             System.out.println(l);
  258.         }
  259.     }
  260.  
  261.     /**
  262.      * Prints the status of the execution, with the exceptions that has occur
  263.      */
  264.     public void printStatus() {
  265.         try {
  266.             finalize();
  267.         } catch (Exception e) {
  268.             e.printStackTrace();
  269.         }
  270.         if (!TemplateThread.hasException) {
  271.             int poeni = 25;
  272.             if (PointsException.getTotalPoints() == 0) {
  273.                 System.out
  274.                         .println("Procesot e uspesno sinhroniziran. Osvoeni 25 poeni.");
  275.             } else {
  276.                 poeni -= PointsException.getTotalPoints();
  277.                 PointsException.printErrors();
  278.                 System.out.println("Maksimalni osvoeni poeni: " + poeni);
  279.             }
  280.  
  281.         } else {
  282.             System.out
  283.                     .println("Procesot ne e sinhroniziran spored uslovite na zadacata");
  284.             printLog();
  285.             System.out
  286.                     .println("====================================================");
  287.             PointsException.printErrors();
  288.             int total = (25 - PointsException.getTotalPoints());
  289.             if (total < 0) {
  290.                 total = 0;
  291.             }
  292.             System.out.println("Maksimum Poeni: " + total);
  293.         }
  294.  
  295.     }
  296. }
  297.  
  298. class PointsException extends RuntimeException {
  299.  
  300.     private static HashMap<String, PointsException> exceptions = new HashMap<String, PointsException>();
  301.     private int points;
  302.  
  303.     public PointsException(int points, String message) {
  304.         super(message);
  305.         this.points = points;
  306.         exceptions.put(message, this);
  307.     }
  308.  
  309.     public static int getTotalPoints() {
  310.         int sum = 0;
  311.         for (PointsException e : exceptions.values()) {
  312.             sum += e.getPoints();
  313.         }
  314.         return sum;
  315.     }
  316.  
  317.     public static void printErrors() {
  318.         if (!exceptions.isEmpty()) {
  319.             System.out.println("Gi imate slednite greski: ");
  320.             for (Map.Entry<String, PointsException> e : exceptions.entrySet()) {
  321.                 System.out.println(String.format("[%s] : (-%d)", e.getKey(), e
  322.                         .getValue().getPoints()));
  323.             }
  324.         }
  325.     }
  326.  
  327.     public int getPoints() {
  328.         return points;
  329.     }
  330. }
  331.  
  332. class Switcher {
  333.     private static final Random RANDOM = new Random();
  334.  
  335.     /*
  336.      * This method pauses the current thread i.e. changes its state to be
  337.      * Blocked. This should force thread switch if there are threads waiting
  338.      */
  339.     public static void forceSwitch(int range) {
  340.         try {
  341.             Thread.sleep(RANDOM.nextInt(range));
  342.         } catch (InterruptedException e) {
  343.         }
  344.     }
  345. }
  346.  
  347. abstract class TemplateThread extends Thread {
  348.  
  349.     static boolean hasException = false;
  350.     public int iteration = 0;
  351.     protected Exception exception = null;
  352.     int numRuns = 1;
  353.  
  354.     public TemplateThread(int numRuns) {
  355.         this.numRuns = numRuns;
  356.     }
  357.  
  358.     public abstract void execute() throws InterruptedException;
  359.  
  360.     @Override
  361.     public void run() {
  362.         try {
  363.             for (int i = 0; i < numRuns&&!hasException; i++) {
  364.                 execute();
  365.                 iteration++;
  366.  
  367.             }
  368.         } catch (InterruptedException e) {
  369.             // Do nothing
  370.         } catch (Exception e) {
  371.             exception = e;
  372.             e.printStackTrace();
  373.             hasException = true;
  374.         }
  375.     }
  376.  
  377.     public void setException(Exception exception) {
  378.         this.exception = exception;
  379.         hasException = true;
  380.     }
  381.  
  382.     @Override
  383.     public String toString() {
  384.         Thread current = Thread.currentThread();
  385.         if (numRuns > 1) {
  386.             return String.format("[%d]%s\t%d\t%d", new Date().getTime(), ""
  387.                             + current.getClass().getSimpleName().charAt(0), getId(),
  388.                     iteration);
  389.         } else {
  390.             return String.format("[%d]%s\t%d\t", new Date().getTime(), ""
  391.                     + current.getClass().getSimpleName().charAt(0), getId());
  392.         }
  393.     }
  394. }
  395.  
  396. class BoundCounterWithRaceConditionCheck {
  397.  
  398.     private static final int RACE_CONDITION_POINTS = 25;
  399.     private static final String RACE_CONDITION_MESSAGE = "Race condition occured";
  400.  
  401.     private int value;
  402.     private Integer maxAllowed;
  403.     private Integer minAllowed;
  404.     private int maxErrorPoints;
  405.     private int minErrorPoints;
  406.     private String maxErrorMessage;
  407.     private String minErrorMessage;
  408.  
  409.     public static int raceConditionDefaultTime = 3;
  410.  
  411.     private int max;
  412.  
  413.     /**
  414.      *
  415.      * @param value
  416.      */
  417.     public BoundCounterWithRaceConditionCheck(int value) {
  418.         super();
  419.         this.value = value;
  420.         this.max = value;
  421.     }
  422.  
  423.     /**
  424.      *
  425.      * @param value
  426.      *            initial value
  427.      * @param maxAllowed
  428.      *            upper bound of the value
  429.      * @param maxErrorPoints
  430.      *            how many points are lost with the max value constraint
  431.      *            violation
  432.      * @param maxErrorMessage
  433.      *            message shown when the upper bound constrain is violated
  434.      * @param minAllowed
  435.      *            lower bound of the value
  436.      * @param minErrorPoints
  437.      *            how many points are lost with the min value constraint
  438.      *            violation
  439.      * @param minErrorMessage
  440.      *            message shown when the lower bound constrain is violated
  441.      */
  442.     public BoundCounterWithRaceConditionCheck(int value, Integer maxAllowed,
  443.                                               int maxErrorPoints, String maxErrorMessage, Integer minAllowed,
  444.                                               int minErrorPoints, String minErrorMessage) {
  445.         super();
  446.         this.value = value;
  447.         this.max = value;
  448.         this.maxAllowed = maxAllowed;
  449.         this.minAllowed = minAllowed;
  450.         this.maxErrorPoints = maxErrorPoints;
  451.         this.minErrorPoints = minErrorPoints;
  452.         this.maxErrorMessage = maxErrorMessage;
  453.         this.minErrorMessage = minErrorMessage;
  454.     }
  455.  
  456.     /**
  457.      *
  458.      * @return the maximum value of the integer variable that occurred at some
  459.      *         point of the execution
  460.      */
  461.     public int getMax() {
  462.         return max;
  463.     }
  464.  
  465.     /**
  466.      *
  467.      * @return the current value
  468.      */
  469.     public synchronized int getValue() {
  470.         return value;
  471.     }
  472.  
  473.     public synchronized void setValue(int value) {
  474.         this.value = value;
  475.     }
  476.  
  477.     /**
  478.      * Throws exception when the val is different than the value of the counter.
  479.      *
  480.      * @param val
  481.      * @param points
  482.      * @param errorMessage
  483.      * @return
  484.      */
  485.     public synchronized PointsException assertEquals(int val, int points,
  486.                                                      String errorMessage) {
  487.         if (this.value != val) {
  488.             PointsException e = new PointsException(points, errorMessage);
  489.             return e;
  490.         } else {
  491.             return null;
  492.         }
  493.     }
  494.  
  495.     public synchronized PointsException assertNotEquals(int val, int points,
  496.                                                         String errorMessage) {
  497.         if (this.value == val) {
  498.             PointsException e = new PointsException(points, errorMessage);
  499.             return e;
  500.         } else {
  501.             return null;
  502.         }
  503.     }
  504.  
  505.     /**
  506.      * Testing for race condition. NOTE: there are no guarantees that the race
  507.      * condition will be detected
  508.      *
  509.      * @return
  510.      */
  511.     public PointsException checkRaceCondition() {
  512.         return checkRaceCondition(raceConditionDefaultTime,
  513.                 RACE_CONDITION_MESSAGE);
  514.     }
  515.  
  516.     /**
  517.      * Testing for race condition. NOTE: there are no guarantees that the race
  518.      * condition will be detected, but higher the time argument is, the
  519.      * probability for race condition occurrence is higher
  520.      *
  521.      * @return
  522.      */
  523.     public PointsException checkRaceCondition(int time, String message) {
  524.         int val;
  525.  
  526.         synchronized (this) {
  527.             val = value;
  528.         }
  529.         Switcher.forceSwitch(time);
  530.         if (val != value) {
  531.             PointsException e = new PointsException(RACE_CONDITION_POINTS,
  532.                     message);
  533.             return e;
  534.         }
  535.         return null;
  536.  
  537.     }
  538.  
  539.     public PointsException incrementWithMax() {
  540.         return incrementWithMax(true);
  541.     }
  542.  
  543.     public PointsException incrementWithMax(boolean checkRaceCondition) {
  544.         if (checkRaceCondition) {
  545.             PointsException raceCondition = checkRaceCondition();
  546.             if (raceCondition != null) {
  547.                 return raceCondition;
  548.             }
  549.         }
  550.         synchronized (this) {
  551.             value++;
  552.  
  553.             if (value > max) {
  554.                 max = value;
  555.             }
  556.             if (maxAllowed != null) {
  557.                 if (value > maxAllowed) {
  558.                     PointsException e = new PointsException(maxErrorPoints,
  559.                             maxErrorMessage);
  560.                     return e;
  561.                 }
  562.             }
  563.         }
  564.  
  565.         return null;
  566.     }
  567.  
  568.     public PointsException decrementWithMin() {
  569.         return decrementWithMin(true);
  570.     }
  571.  
  572.     public PointsException decrementWithMin(boolean checkRaceCondition) {
  573.         if (checkRaceCondition) {
  574.             PointsException raceCondition = checkRaceCondition();
  575.             if (raceCondition != null) {
  576.                 return raceCondition;
  577.             }
  578.         }
  579.  
  580.         synchronized (this) {
  581.             value--;
  582.             if (minAllowed != null) {
  583.                 if (value < minAllowed) {
  584.                     PointsException e = new PointsException(minErrorPoints,
  585.                             minErrorMessage);
  586.                     return e;
  587.                 }
  588.             }
  589.         }
  590.         return null;
  591.     }
  592.  
  593. }
  594.  
  595. abstract class ProblemExecution {
  596.  
  597.     public static void start(HashSet<Thread> threads, AbstractState state)
  598.             throws Exception {
  599.  
  600.         startWithoutDeadlock(threads, state);
  601.  
  602.         checkDeadlock(threads, state);
  603.     }
  604.  
  605.     public static void startWithoutDeadlock(HashSet<Thread> threads,
  606.                                             AbstractState state) throws Exception {
  607.  
  608.         // start the threads
  609.         for (Thread t : threads) {
  610.             t.start();
  611.         }
  612.  
  613.         // wait threads to finish
  614.         for (Thread t : threads) {
  615.             t.join(1000);
  616.         }
  617.  
  618.     }
  619.  
  620.     private static void checkDeadlock(HashSet<Thread> threads,
  621.                                       AbstractState state) {
  622.         // check for deadlock
  623.         for (Thread t : threads) {
  624.             if (t.isAlive()) {
  625.                 t.interrupt();
  626.                 if (t instanceof TemplateThread) {
  627.                     TemplateThread tt = (TemplateThread) t;
  628.                     tt.setException(new PointsException(25, "DEADLOCK"));
  629.                 }
  630.             }
  631.         }
  632.  
  633.         // print the status
  634.         state.printStatus();
  635.     }
  636. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement