diff --git a/src/exercises/ex_z4/AuctionMain.java b/src/exercises/ex_z4/AuctionMain.java index 8f25ac8..3e4da88 100644 --- a/src/exercises/ex_z4/AuctionMain.java +++ b/src/exercises/ex_z4/AuctionMain.java @@ -1,23 +1,27 @@ package exercises.ex_z4; -import java.util.Random; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.Semaphore; +import java.util.Arrays; + public class AuctionMain { public static final String[] names = { "Sabrina", "José", "Patrick", "Salomé", "Lisa", "Alfred", "Annna", "Alex", "Kevin" }; + public static final Item[] items = { + new Item("Album de Sabrina Carpenter"), + new Item("Chaussette gauche de Freddie Mercury"), + new Item("Peigne de Michael Jackson"), + new Item("Décapsuleur de Kurt Cobain") + }; + public static void main(String[] args) { - Semaphore mutex = new Semaphore(1); - ConcurrentLinkedQueue bids = new ConcurrentLinkedQueue<>(); - Auctioneer auctioneer = new Auctioneer("Paul", bids, mutex); + Auctioneer auctioneer = new Auctioneer("Paul", Arrays.asList(items)); new Thread(auctioneer).start(); for (int i = 0; i < names.length; i++) { - new Thread(new Bidder(names[i])).start(); + new Thread(new Bidder(names[i], auctioneer)).start(); } } } diff --git a/src/exercises/ex_z4/AuctionState.java b/src/exercises/ex_z4/AuctionState.java new file mode 100644 index 0000000..02f602c --- /dev/null +++ b/src/exercises/ex_z4/AuctionState.java @@ -0,0 +1,8 @@ +package exercises.ex_z4; + +public enum AuctionState { + PRESENTING_ITEM, + BIDDING, + SOLD, + FINISHED +} diff --git a/src/exercises/ex_z4/Auctioneer.java b/src/exercises/ex_z4/Auctioneer.java index a9ff427..4f8d249 100644 --- a/src/exercises/ex_z4/Auctioneer.java +++ b/src/exercises/ex_z4/Auctioneer.java @@ -1,23 +1,45 @@ package exercises.ex_z4; +import java.util.List; +import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.Semaphore; + + +import static exercises.ex_z4.AuctionState.*; public class Auctioneer implements Runnable { private String name; - private ConcurrentLinkedQueue bids; - private Semaphore mutex; + private Queue bids = new ConcurrentLinkedQueue<>(); private Bid maximumBid; private Thread countdownThread = null; + private boolean isAuctionActive = false; + private AuctionState auctionState = PRESENTING_ITEM; + private final List items; - public Auctioneer(String name, ConcurrentLinkedQueue bids, Semaphore mutex) { + + public Auctioneer(String name, List items) { this.name = name; - this.bids = bids; - this.mutex = mutex; + this.items = items; + } + + private void announce(String msg) { + System.out.println("[Auctioneer] " + msg); + } + + public void presentItem() throws InterruptedException { + Item item = items.getFirst(); + announce("Now selling this new item: '" + item.name() + "'"); + announce("Get ready to bid..."); + Thread.sleep(2000); + announce("Bidding open !"); + auctionState = BIDDING; } public void placeBid(Bid bid) { - bids.add(bid); + if (auctionState == BIDDING) { + System.out.println(bid.bidder() + " bids $" + bid.amount()); + bids.add(bid); + } notify(); } @@ -30,7 +52,7 @@ public class Auctioneer implements Runnable { Thread.sleep(1000); System.out.println("One"); Thread.sleep(1000); - System.out.println("End of the Auction !"); + auctionState = SOLD; notify(); } catch (InterruptedException _) {} } @@ -44,38 +66,52 @@ public class Auctioneer implements Runnable { return maximumBid; } - public void endAuction(){ - System.out.println("End of the auction ! "); - notifyAll(); + public AuctionState getAuctionState() { + return auctionState; + } + + public void finalizeBidding() throws InterruptedException { + announce("And sold for $" + maximumBid.amount() + " !"); + Item item = items.removeFirst(); + announce(maximumBid.bidder() + " is now the proud owner of " + item); + maximumBid.bidder().addItem(item); + Thread.sleep(2000); + if (items.isEmpty()) { + auctionState = FINISHED; + } else { + auctionState = PRESENTING_ITEM; + } } @Override public void run() { - while (true) { + while (auctionState != FINISHED) { try { - mutex.acquire(); - Bid current_bid = bids.poll(); - if (current_bid == null) { - startCountdown(); - wait(); - if (bids.isEmpty()) { - endAuction(); + switch (auctionState) { + case PRESENTING_ITEM -> { + presentItem(); } - continue; - } - if (!bids.isEmpty()) { - if (current_bid.amount() > maximumBid.amount()) { - maximumBid = current_bid; - System.out.println("New bid : " + maximumBid.amount() + " by " + maximumBid.bidder()); - mutex.release(); - return; + case BIDDING -> { + Bid current_bid = bids.poll(); + if (current_bid == null) { + startCountdown(); + wait(); + } else { + if (current_bid.amount() > maximumBid.amount()) { + maximumBid = current_bid; + announce("New best bid : " + maximumBid.amount() + " by " + maximumBid.bidder()); + } + } + } + case SOLD -> { + finalizeBidding(); } - } else { - mutex.release(); } + } catch (InterruptedException e) { throw new RuntimeException(e); } } + announce("The auction is now finished ! Thank you for participating !"); } } diff --git a/src/exercises/ex_z4/Bidder.java b/src/exercises/ex_z4/Bidder.java index 4417fc9..a4a8e5c 100644 --- a/src/exercises/ex_z4/Bidder.java +++ b/src/exercises/ex_z4/Bidder.java @@ -1,30 +1,53 @@ package exercises.ex_z4; +import exercises.Utils; + import java.util.Random; import java.util.ArrayList; import java.util.List; +import static exercises.ex_z4.AuctionState.BIDDING; +import static exercises.ex_z4.AuctionState.FINISHED; + public class Bidder implements Runnable { private static int nextId = 0; private final String name; private final int id; private final List items = new ArrayList<>(); private Double lastBid = null; + private final Auctioneer auctioneer; - public Bidder(String name) { + public Bidder(String name, Auctioneer auctioneer) { this.name = name; this.id = nextId++; + this.auctioneer = auctioneer; } @Override public void run() { - while(true){ - Random rand = new Random(); - double addon = rand.nextDouble(500); - lastBid += addon; + while (true) { + AuctionState state = auctioneer.getAuctionState(); + if (state == BIDDING) { + Random rand = new Random(); + double addon = rand.nextDouble(500); + double base = auctioneer.getMaximumBid().amount(); + lastBid = base + addon; + auctioneer.placeBid(new Bid(this, lastBid)); + try { + Utils.randomSleep(100, 5000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } else if (state == FINISHED) { + break; + } } } + public void addItem(Item item){ + items.add(item); + } + public String getName() { return name; }