Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package lab1;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Queue;
- import java.util.concurrent.ConcurrentLinkedQueue;
- import java.util.concurrent.CountDownLatch;
- import java.util.concurrent.atomic.AtomicBoolean;
- import java.util.concurrent.atomic.AtomicInteger;
- import java.util.concurrent.atomic.AtomicReference;
- import java.util.stream.Collectors;
- import lab1.Table.QueueItem;
- class Table implements Runnable {
- static final class QueueItem {
- private final Philosopher philosopher;
- private final CountDownLatch awaitingLock;
- private final List<Fork> forks;
- public QueueItem(Philosopher philosopher, List<Fork> forks) {
- this.philosopher = philosopher;
- this.forks = forks;
- this.awaitingLock = new CountDownLatch(1);
- }
- @Override
- public String toString() {
- return "QueueItem [philosopher=" + philosopher + ", awaitingLock=" + awaitingLock + ", forks=" + forks
- + "]";
- }
- }
- private final List<Fork> forks;
- private final List<Philosopher> philosophers;
- private final Queue<QueueItem> hungryQueue;
- private final Queue<QueueItem> releaseQueue;
- public Table(int count) {
- this.hungryQueue = new ConcurrentLinkedQueue<>();
- this.releaseQueue = new ConcurrentLinkedQueue<>();
- forks = new ArrayList<>();
- philosophers = new ArrayList<>();
- for (int i = 0; i < count; i++) {
- forks.add(new Fork(i));
- }
- for (int i = 0; i < count; i++) {
- List<Fork> ownableForks = new ArrayList<>();
- ownableForks.add(forks.get(i));
- ownableForks.add(forks.get((i + 1) % 6));
- philosophers.add(new Philosopher(i, ownableForks, this));
- }
- }
- public List<Philosopher> getPhilosophers() {
- return philosophers;
- }
- public QueueItem giveMeForks(Philosopher philosopher, List<Fork> forks) throws InterruptedException {
- QueueItem item = new QueueItem(philosopher, forks);
- hungryQueue.add(item);
- item.awaitingLock.await();
- return item;
- }
- public void releaseForks(QueueItem item) {
- this.releaseQueue.add(item);
- }
- @Override
- public void run() {
- while (true) {
- while (!releaseQueue.isEmpty()) {
- final QueueItem item = releaseQueue.poll();
- item.forks.forEach(fork -> {
- if (!fork.releaseOwnedBy(item)) {
- System.err.println("Failed to release " + fork + " from " + item);
- }
- });
- }
- final QueueItem item = this.hungryQueue.poll();
- if (item == null) continue;
- final List<Fork> acquired = new ArrayList<>();
- for (Fork fork: item.forks) {
- if (fork.setOwnedBy(item, Fork.OWNED_BY_NO_ONE)) {
- acquired.add(fork);
- } else {
- // System.err.println("Fork acquire interrupted in middle for " + fork + ", " + item);
- for (Fork acquiredFork : acquired) {
- acquiredFork.releaseOwnedBy(item);
- }
- }
- }
- if (acquired.size() == 2) {
- item.awaitingLock.countDown();
- }
- }
- }
- }
- class Fork {
- static final QueueItem OWNED_BY_NO_ONE = null;
- private final int idx;
- private final AtomicReference<QueueItem> ownedBy;
- public Fork(int idx) {
- this.idx = idx;
- this.ownedBy = new AtomicReference<>(OWNED_BY_NO_ONE);
- }
- public int getIdx() {
- return idx;
- }
- public QueueItem getOwnedBy() {
- return ownedBy.get();
- }
- public boolean setOwnedBy(QueueItem ownedBy, QueueItem expectedOwnedBy) {
- return this.ownedBy.compareAndSet(expectedOwnedBy, ownedBy);
- }
- public boolean releaseOwnedBy(QueueItem expectedOwnedBy) {
- return this.ownedBy.compareAndSet(expectedOwnedBy, OWNED_BY_NO_ONE);
- }
- @Override
- public String toString() {
- return "Fork [idx=" + idx + ", ownedBy=" + ownedBy.hashCode() + "]";
- }
- }
- class Philosopher implements Runnable {
- // milliseconds
- private static final int TIME_TO_EAT = 10_000;
- private final Table ctx;
- private final int idx;
- private final List<Fork> owns;
- private final List<Fork> wantsToOwn;
- public Philosopher(int idx, List<Fork> wantsToOwn, Table ctx) {
- this.idx = idx;
- this.owns = new ArrayList<>();
- this.ctx = ctx;
- this.wantsToOwn = wantsToOwn;
- }
- public int getIdx() {
- return idx;
- }
- @Override
- public String toString() {
- return "Philosopher [ctx=" + ctx + ", idx=" + idx + ", owns=" + owns + ", wantsToOwn=" + wantsToOwn + "]";
- }
- public void run() {
- try {
- while (true) {
- // System.out.println(this);
- final QueueItem lock = ctx.giveMeForks(this, wantsToOwn);
- owns.addAll(wantsToOwn);
- System.out.println("Eating: " + this);
- Thread.sleep(TIME_TO_EAT);
- owns.clear();
- ctx.releaseForks(lock);
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- public class Main {
- public static void main(String[] args) {
- Table table = new Table(6);
- for (Runnable run : table.getPhilosophers()) {
- new Thread(run).start();
- }
- new Thread(table).start();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement