Advertisement
Guest User

philosophae

a guest
Sep 19th, 2019
145
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.81 KB | None | 0 0
  1. package lab1;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import java.util.Queue;
  6. import java.util.concurrent.ConcurrentLinkedQueue;
  7. import java.util.concurrent.CountDownLatch;
  8. import java.util.concurrent.atomic.AtomicBoolean;
  9. import java.util.concurrent.atomic.AtomicInteger;
  10. import java.util.concurrent.atomic.AtomicReference;
  11. import java.util.stream.Collectors;
  12.  
  13. import lab1.Table.QueueItem;
  14.  
  15. class Table implements Runnable {
  16.  
  17.     static final class QueueItem {
  18.         private final Philosopher philosopher;
  19.         private final CountDownLatch awaitingLock;
  20.         private final List<Fork> forks;
  21.  
  22.         public QueueItem(Philosopher philosopher, List<Fork> forks) {
  23.             this.philosopher = philosopher;
  24.             this.forks = forks;
  25.             this.awaitingLock = new CountDownLatch(1);
  26.         }
  27.  
  28.         @Override
  29.         public String toString() {
  30.             return "QueueItem [philosopher=" + philosopher + ", awaitingLock=" + awaitingLock + ", forks=" + forks
  31.                     + "]";
  32.         }
  33.     }
  34.  
  35.     private final List<Fork> forks;
  36.     private final List<Philosopher> philosophers;
  37.  
  38.     private final Queue<QueueItem> hungryQueue;
  39.     private final Queue<QueueItem> releaseQueue;
  40.  
  41.     public Table(int count) {
  42.         this.hungryQueue = new ConcurrentLinkedQueue<>();
  43.         this.releaseQueue = new ConcurrentLinkedQueue<>();
  44.  
  45.         forks = new ArrayList<>();
  46.         philosophers = new ArrayList<>();
  47.  
  48.         for (int i = 0; i < count; i++) {
  49.             forks.add(new Fork(i));
  50.         }
  51.  
  52.         for (int i = 0; i < count; i++) {
  53.             List<Fork> ownableForks = new ArrayList<>();
  54.             ownableForks.add(forks.get(i));
  55.             ownableForks.add(forks.get((i + 1) % 6));
  56.            
  57.             philosophers.add(new Philosopher(i, ownableForks, this));
  58.         }
  59.     }
  60.  
  61.     public List<Philosopher> getPhilosophers() {
  62.         return philosophers;
  63.     }
  64.  
  65.     public QueueItem giveMeForks(Philosopher philosopher, List<Fork> forks) throws InterruptedException {
  66.         QueueItem item = new QueueItem(philosopher, forks);
  67.         hungryQueue.add(item);
  68.         item.awaitingLock.await();
  69.         return item;
  70.     }
  71.  
  72.     public void releaseForks(QueueItem item) {
  73.         this.releaseQueue.add(item);
  74.     }
  75.  
  76.     @Override
  77.     public void run() {
  78.         while (true) {
  79.             while (!releaseQueue.isEmpty()) {
  80.                 final QueueItem item = releaseQueue.poll();
  81.                 item.forks.forEach(fork -> {
  82.                     if (!fork.releaseOwnedBy(item)) {
  83.                         System.err.println("Failed to release " + fork + " from " + item);
  84.                     }
  85.                 });
  86.             }
  87.            
  88.             final QueueItem item = this.hungryQueue.poll();
  89.             if (item == null) continue;
  90.            
  91.             final List<Fork> acquired = new ArrayList<>();
  92.             for (Fork fork: item.forks) {
  93.                 if (fork.setOwnedBy(item, Fork.OWNED_BY_NO_ONE)) {
  94.                     acquired.add(fork);
  95.                 } else {
  96. //                  System.err.println("Fork acquire interrupted in middle for " + fork + ", " + item);
  97.                     for (Fork acquiredFork : acquired) {
  98.                         acquiredFork.releaseOwnedBy(item);
  99.                     }
  100.                 }
  101.             }
  102.             if (acquired.size() == 2) {
  103.                 item.awaitingLock.countDown();
  104.             }
  105.         }
  106.     }
  107. }
  108.  
  109. class Fork {
  110.     static final QueueItem OWNED_BY_NO_ONE = null;
  111.  
  112.     private final int idx;
  113.     private final AtomicReference<QueueItem> ownedBy;
  114.  
  115.     public Fork(int idx) {
  116.         this.idx = idx;
  117.         this.ownedBy = new AtomicReference<>(OWNED_BY_NO_ONE);
  118.     }
  119.  
  120.     public int getIdx() {
  121.         return idx;
  122.     }
  123.  
  124.     public QueueItem getOwnedBy() {
  125.         return ownedBy.get();
  126.     }
  127.  
  128.     public boolean setOwnedBy(QueueItem ownedBy, QueueItem expectedOwnedBy) {
  129.         return this.ownedBy.compareAndSet(expectedOwnedBy, ownedBy);
  130.     }
  131.  
  132.     public boolean releaseOwnedBy(QueueItem expectedOwnedBy) {
  133.         return this.ownedBy.compareAndSet(expectedOwnedBy, OWNED_BY_NO_ONE);
  134.     }
  135.  
  136.     @Override
  137.     public String toString() {
  138.         return "Fork [idx=" + idx + ", ownedBy=" + ownedBy.hashCode() + "]";
  139.     }
  140. }
  141.  
  142. class Philosopher implements Runnable {
  143.  
  144.     // milliseconds
  145.     private static final int TIME_TO_EAT = 10_000;
  146.  
  147.     private final Table ctx;
  148.  
  149.     private final int idx;
  150.  
  151.     private final List<Fork> owns;
  152.     private final List<Fork> wantsToOwn;
  153.  
  154.     public Philosopher(int idx, List<Fork> wantsToOwn, Table ctx) {
  155.         this.idx = idx;
  156.         this.owns = new ArrayList<>();
  157.         this.ctx = ctx;
  158.         this.wantsToOwn = wantsToOwn;
  159.     }
  160.  
  161.     public int getIdx() {
  162.         return idx;
  163.     }
  164.  
  165.     @Override
  166.     public String toString() {
  167.         return "Philosopher [ctx=" + ctx + ", idx=" + idx + ", owns=" + owns + ", wantsToOwn=" + wantsToOwn + "]";
  168.     }
  169.  
  170.     public void run() {
  171.         try {
  172.             while (true) {
  173. //              System.out.println(this);
  174.                 final QueueItem lock = ctx.giveMeForks(this, wantsToOwn);
  175.                 owns.addAll(wantsToOwn);
  176.                 System.out.println("Eating: " + this);
  177.                 Thread.sleep(TIME_TO_EAT);
  178.                 owns.clear();
  179.                 ctx.releaseForks(lock);
  180.             }
  181.         } catch (InterruptedException e) {
  182.             e.printStackTrace();
  183.         }
  184.     }
  185. }
  186.  
  187. public class Main {
  188.  
  189.     public static void main(String[] args) {
  190.         Table table = new Table(6);
  191.         for (Runnable run : table.getPhilosophers()) {
  192.             new Thread(run).start();
  193.         }
  194.         new Thread(table).start();
  195.     }
  196. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement