Compare commits
22 Commits
b3a0d1f7a1
...
main
Author | SHA1 | Date | |
---|---|---|---|
b5540fc68d
|
|||
fd3af32c7c
|
|||
886bf5a1cd
|
|||
afc2fbfa8a
|
|||
c7d054e973
|
|||
fe3d1aac35
|
|||
e959cdd466
|
|||
1cfc40afed
|
|||
28ab30e735
|
|||
c89a9b3a90
|
|||
9be4e8a359
|
|||
dbd83223fe
|
|||
a7216b1642
|
|||
53add330f4
|
|||
508d412a1a
|
|||
532a727b43
|
|||
8374825610
|
|||
bc4dfb6ef0
|
|||
1255f304fc
|
|||
f2bb16ea85
|
|||
3c6d89bdd8
|
|||
a1bfa6021a
|
124
.idea/uiDesigner.xml
generated
Normal file
124
.idea/uiDesigner.xml
generated
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Palette2">
|
||||||
|
<group name="Swing">
|
||||||
|
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="Button" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="RadioButton" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="CheckBox" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="Label" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||||
|
<preferred-size width="150" height="-1" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||||
|
<preferred-size width="150" height="-1" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||||
|
<preferred-size width="150" height="-1" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||||
|
<preferred-size width="200" height="200" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||||
|
<preferred-size width="200" height="200" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||||
|
<preferred-size width="-1" height="20" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||||
|
</item>
|
||||||
|
</group>
|
||||||
|
</component>
|
||||||
|
</project>
|
80
README.md
Normal file
80
README.md
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# Concurrent Programming
|
||||||
|
|
||||||
|
This repository holds all my answers to the exercises for the 202.2 Concurrent Programming course
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Some exercises may not be complete, although most of them are fully functioning
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
* [Exercises](#exercises)
|
||||||
|
* [Lab 01 - Thread Objects and Synchronization](#lab-01---thread-objects-and-synchronization)
|
||||||
|
* [Lab 01 (bis) - Thread Objects and Synchronization](#lab-01-bis---thread-objects-and-synchronization)
|
||||||
|
* [Lab 02 - Liveness, Guarded Blocks and Immutable Objects](#lab-02---liveness-guarded-blocks-and-immutable-objects)
|
||||||
|
* [Lab 02 (bis) - Liveness, Guarded Blocks and Immutable Objects](#lab-02-bis---liveness-guarded-blocks-and-immutable-objects)
|
||||||
|
* [Lab 03 - Lock Objects](#lab-03---lock-objects)
|
||||||
|
* [Lab 03 (bis) - Lock Objects](#lab-03-bis---lock-objects)
|
||||||
|
* [Lab 04 - Executors, Callable and Fork-Join](#lab-04---executors-callable-and-fork-join)
|
||||||
|
* [Lab 05 - Concurrent Collections and Atomic Variables](#lab-05---concurrent-collections-and-atomic-variables)
|
||||||
|
* [Lab 06 - Synchronizers](#lab-06---synchronizers)
|
||||||
|
* [Lab 07 (Workshop) - Summarizing exercises](#lab-07-workshop---summarizing-exercises)
|
||||||
|
|
||||||
|
## Exercises
|
||||||
|
### Lab 01 - Thread Objects and Synchronization
|
||||||
|
- [A: Defining and Starting A Thread](src/exercises/ex_a/TestingSimpleThreads.java)
|
||||||
|
- [B: Pausing Execution With Sleep](src/exercises/ex_b/TestingSleep.java)
|
||||||
|
- [C: Interruptions](src/exercises/ex_c/TestingSleep.java)
|
||||||
|
- [D: Joins](src/exercises/ex_d/TestingJoins.java)
|
||||||
|
- [E: Thread Interference: Managing Bank Accounts](src/exercises/ex_e/TestingThreadInterferences.java)
|
||||||
|
- [F: Synchronized Methods: Ensuring consistent operations on bank accounts](src/exercises/ex_f/TestingThreadInterferences.java)
|
||||||
|
- [G: Synchronized Statements](src/exercises/ex_g/TestingSynchronizedStatements.java)
|
||||||
|
|
||||||
|
### Lab 01 (bis) - Thread Objects and Synchronization
|
||||||
|
- [Dbis: Joins](src/exercises/ex_d_bis/TestStepThreads.java)
|
||||||
|
|
||||||
|
### Lab 02 - Liveness, Guarded Blocks and Immutable Objects
|
||||||
|
- [H1: Refactoring from Deadlocks](src/exercises/ex_h1/TestThreadWithDeadlock.java)
|
||||||
|
- [H2: Bridge crossing without deadlock](src/exercises/ex_h2/TestDeadlockBridge.java)
|
||||||
|
- [I: Starvation: simulating the access of employees to a conference room](src/exercises/ex_i/TestingStarvation.java)
|
||||||
|
- [J: Livelock : couple eating](src/exercises/ex_j/LivelockDinner.java)
|
||||||
|
- [K: Guarded Blocks : managing packages in a post office](src/exercises/ex_k/TestingGuardedBlocks.java)
|
||||||
|
- ~~L: Immutable objects: From person to statue~~
|
||||||
|
|
||||||
|
### Lab 02 (bis) - Liveness, Guarded Blocks and Immutable Objects
|
||||||
|
- [Kbis1: Guarded Blocks : a service desk](src/exercises/ex_k_bis1/TestServiceDesk.java)
|
||||||
|
- ~~Kbis2: Playing Tennis~~
|
||||||
|
|
||||||
|
### Lab 03 - Lock Objects
|
||||||
|
- ~~M: ReentrantLock: Sharing a Vehicle in a couple~~
|
||||||
|
- [N: ReentrantReadWriteLock: News Feed](src/exercises/ex_n/TestingReentrantReadWriteLock_News.java)
|
||||||
|
- [O: ReentrantLockWithConditions: NumberProducersConsumers](src/exercises/ex_o/TestingReentrantLockWithConditions.java)
|
||||||
|
|
||||||
|
### Lab 03 (bis) - Lock Objects
|
||||||
|
- [Nbis: ReentrantReadWriteLock: Managing a library catalog system](src/exercises/ex_n_bis/LibraryCatalog.java)
|
||||||
|
|
||||||
|
### Lab 04 - Executors, Callable and Fork-Join
|
||||||
|
- [P: Executors for Drums](src/exercises/ex_p/Partition.java)
|
||||||
|
- [Pbis: Christmas Lights Task Scheduler](src/exercises/ex_p_bis/ChristmasTreeTester.java)
|
||||||
|
- [Q1: Callables and Futures for a Pizzeria](src/exercises/ex_q1/Pizzeria.java)
|
||||||
|
- [Q2: Fork/Join: Song](src/exercises/ex_q2/ForkJoinTest.java)
|
||||||
|
- [Q3: Arrays.parallelSort](src/exercises/ex_q3/Library.java)
|
||||||
|
- ~~Q4: Concurrent Array Sum Calculation~~
|
||||||
|
|
||||||
|
### Lab 05 - Concurrent Collections and Atomic Variables
|
||||||
|
- [R: BlockingQueue: Simulating a PostOffice](src/exercises/ex_r/TestingBlockingQueue_PostOffice.java)
|
||||||
|
- [S1: ConcurrentHashMap in the Farm](src/exercises/ex_s1/TestingConcurrentHashMap_Farm.java)
|
||||||
|
- [S2: Comparing Atomic Arrays and Standard Arrays](src/exercises/ex_s2/TestingAtomicInteger.java)
|
||||||
|
- [S3: java.util.concurrent.atomic package: Creativity](src/exercises/ex_s3/TestingAtomicLong.java)
|
||||||
|
|
||||||
|
### Lab 06 - Synchronizers
|
||||||
|
- [T: Semaphore for Dog Feeding](src/exercises/ex_t/TestingSemaphore_DogBreeder.java)
|
||||||
|
- [U: CountDownLatch: Starting the Family Trip](src/exercises/ex_u/TestingCountDownLatch_FamilyTrip.java)
|
||||||
|
- [V: CyclicBarrier: Patrouille de Glaciers](src/exercises/ex_v/TestingCyclicBarrier_PDG.java)
|
||||||
|
- [W: Exchanger: Bring my Car to the Garage](src/exercises/ex_w/TestingExchanger_Garage.java)
|
||||||
|
- [X: Phaser for the Next Family Bike Trip](src/exercises/ex_x/TestingPhaserFamilyBikeTrip.java)
|
||||||
|
- [y: Synchronized Race (former exam)](src/exercises/ex_y/RaceTester.java)
|
||||||
|
|
||||||
|
### Lab 07 (Workshop) - Summarizing exercises
|
||||||
|
- ~~Z1: The dining philosophers~~
|
||||||
|
- ~~Z2: The Sleeping Barber Problem~~
|
||||||
|
- ~~Z3: Print Queue Management~~
|
||||||
|
- [Z4: Concurrent Auction Problem](src/exercises/ex_z4/AuctionMain.java)
|
7
src/exercises/Utils.java
Normal file
7
src/exercises/Utils.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package exercises;
|
||||||
|
|
||||||
|
public class Utils {
|
||||||
|
public static void randomSleep(long min, long max) throws InterruptedException {
|
||||||
|
Thread.sleep((long) (min + Math.random() * max));
|
||||||
|
}
|
||||||
|
}
|
33
src/exercises/ex_j/Diner.java
Normal file
33
src/exercises/ex_j/Diner.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package exercises.ex_j;
|
||||||
|
|
||||||
|
class Diner {
|
||||||
|
private String name;
|
||||||
|
private boolean isHungry;
|
||||||
|
|
||||||
|
public Diner(String name) {
|
||||||
|
this.name = name;
|
||||||
|
isHungry = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHungry() {
|
||||||
|
return isHungry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void eatWith(Spoon spoon, Diner spouse) {
|
||||||
|
while (isHungry) {
|
||||||
|
if (spoon.getOwner() == this) {
|
||||||
|
if (spouse.isHungry()) {
|
||||||
|
System.out.println(getName() + ": You eat first my darling " + spouse.getName() + "!");
|
||||||
|
spoon.setOwner(spouse);
|
||||||
|
} else {
|
||||||
|
spoon.use();
|
||||||
|
this.isHungry = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
src/exercises/ex_j/LivelockDinner.java
Normal file
20
src/exercises/ex_j/LivelockDinner.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package exercises.ex_j;
|
||||||
|
|
||||||
|
public class LivelockDinner {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
final Diner husband = new Diner("Bob");
|
||||||
|
final Diner wife = new Diner("Alice");
|
||||||
|
final Spoon spoon = new Spoon(husband);
|
||||||
|
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
husband.eatWith(spoon, wife);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
wife.eatWith(spoon, husband);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
}
|
21
src/exercises/ex_j/Spoon.java
Normal file
21
src/exercises/ex_j/Spoon.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package exercises.ex_j;
|
||||||
|
|
||||||
|
class Spoon {
|
||||||
|
private Diner owner;
|
||||||
|
|
||||||
|
public synchronized Diner getOwner() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Spoon(Diner d) {
|
||||||
|
owner = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void setOwner(Diner d) {
|
||||||
|
owner = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void use() {
|
||||||
|
System.out.printf("%s has eaten!", owner.getName());
|
||||||
|
}
|
||||||
|
}
|
31
src/exercises/ex_k/Customer.java
Normal file
31
src/exercises/ex_k/Customer.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package exercises.ex_k;
|
||||||
|
|
||||||
|
public class Customer implements Runnable {
|
||||||
|
private String name;
|
||||||
|
private PostOffice postOffice;
|
||||||
|
|
||||||
|
public Customer(String name, PostOffice postOffice) {
|
||||||
|
this.name = name;
|
||||||
|
this.postOffice = postOffice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Package pkg;
|
||||||
|
while (true) {
|
||||||
|
pkg = new Package(this);
|
||||||
|
System.out.println("Registering " + pkg + "...");
|
||||||
|
postOffice.registerPackage(pkg);
|
||||||
|
System.out.println("Registered " + pkg);
|
||||||
|
try {
|
||||||
|
Thread.sleep((long) (Math.random() * 2000 + 1000));
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
src/exercises/ex_k/Package.java
Normal file
15
src/exercises/ex_k/Package.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package exercises.ex_k;
|
||||||
|
|
||||||
|
public class Package {
|
||||||
|
private Customer sender;
|
||||||
|
|
||||||
|
public Package(Customer sender) {
|
||||||
|
this.sender = sender;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Package{" +
|
||||||
|
"sender=" + sender.getName() +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
38
src/exercises/ex_k/PostOffice.java
Normal file
38
src/exercises/ex_k/PostOffice.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package exercises.ex_k;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PostOffice {
|
||||||
|
public static final int CAPACITY = 5;
|
||||||
|
private List<Package> packages = new LinkedList<>();
|
||||||
|
|
||||||
|
public synchronized void registerPackage(Package pkg) {
|
||||||
|
while (packages.size() >= CAPACITY) {
|
||||||
|
try {
|
||||||
|
System.out.println("[PostOffice] Storage is full, waiting");
|
||||||
|
wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
packages.add(pkg);
|
||||||
|
System.out.println("[PostOffice] Storage: " + packages.size() + " / " + CAPACITY);
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Package getNextPackage() {
|
||||||
|
while (packages.isEmpty()) {
|
||||||
|
try {
|
||||||
|
System.out.println("[PostOffice] Storage is empty, waiting");
|
||||||
|
wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Package pkg = packages.removeFirst();
|
||||||
|
System.out.println("[PostOffice] Storage: " + packages.size() + " / " + CAPACITY);
|
||||||
|
notifyAll();
|
||||||
|
return pkg;
|
||||||
|
}
|
||||||
|
}
|
23
src/exercises/ex_k/Postman.java
Normal file
23
src/exercises/ex_k/Postman.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package exercises.ex_k;
|
||||||
|
|
||||||
|
public class Postman implements Runnable {
|
||||||
|
private PostOffice postOffice;
|
||||||
|
|
||||||
|
public Postman(PostOffice postOffice) {
|
||||||
|
this.postOffice = postOffice;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Package pkg;
|
||||||
|
while (true) {
|
||||||
|
pkg = postOffice.getNextPackage();
|
||||||
|
System.out.println("Delivering " + pkg);
|
||||||
|
try {
|
||||||
|
Thread.sleep(2000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
src/exercises/ex_k/TestingGuardedBlocks.java
Normal file
10
src/exercises/ex_k/TestingGuardedBlocks.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package exercises.ex_k;
|
||||||
|
|
||||||
|
public class TestingGuardedBlocks {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
PostOffice postOffice = new PostOffice();
|
||||||
|
(new Thread(new Postman(postOffice))).start();
|
||||||
|
(new Thread(new Customer("Mrs Darbellay", postOffice))).start();
|
||||||
|
(new Thread(new Customer("Mrs Müller", postOffice))).start();
|
||||||
|
}
|
||||||
|
}
|
17
src/exercises/ex_k_bis1/Customer.java
Normal file
17
src/exercises/ex_k_bis1/Customer.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package exercises.ex_k_bis1;
|
||||||
|
|
||||||
|
public class Customer implements Runnable {
|
||||||
|
/*private String name;
|
||||||
|
private ServiceDesk serviceDesk;
|
||||||
|
|
||||||
|
public Customer(String name, ServiceDesk serviceDesk) {
|
||||||
|
this.name = name;
|
||||||
|
this.serviceDesk = serviceDesk;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
22
src/exercises/ex_k_bis1/TestServiceDesk.java
Normal file
22
src/exercises/ex_k_bis1/TestServiceDesk.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package exercises.ex_k_bis1;
|
||||||
|
|
||||||
|
public class TestServiceDesk {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
/*
|
||||||
|
ServiceDesk serviceDesk = new ServiceDesk(2);
|
||||||
|
for (int j = 0; j<3; j++) {
|
||||||
|
new Thread(new ServiceRepresentative(serviceDesk), "Employee-"+ j).start();
|
||||||
|
}
|
||||||
|
// Start customer threads
|
||||||
|
for (int i = 0; i < 10; i++) { // 30 customers
|
||||||
|
String name = "Customer-" + i;
|
||||||
|
new Thread(new Customer(name, serviceDesk)).start();
|
||||||
|
try {
|
||||||
|
Thread.sleep((int) (Math.random() * 1000)); // Random arrival
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
21
src/exercises/ex_n/News.java
Normal file
21
src/exercises/ex_n/News.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package exercises.ex_n;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
public class News {
|
||||||
|
private String news;
|
||||||
|
private LocalDateTime date;
|
||||||
|
|
||||||
|
public News(String news) {
|
||||||
|
this.news = news;
|
||||||
|
this.date = LocalDateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "News{" +
|
||||||
|
"news='" + news + '\'' +
|
||||||
|
", date=" + date +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
37
src/exercises/ex_n/NewsFeed.java
Normal file
37
src/exercises/ex_n/NewsFeed.java
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package exercises.ex_n;
|
||||||
|
|
||||||
|
import java.util.Stack;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
|
public class NewsFeed {
|
||||||
|
private final Stack<News> newsStack = new Stack<>();
|
||||||
|
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||||
|
private final Lock writeLock = lock.writeLock();
|
||||||
|
private final Lock readLock = lock.readLock();
|
||||||
|
|
||||||
|
public NewsFeed() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(News news) {
|
||||||
|
try {
|
||||||
|
writeLock.lock();
|
||||||
|
newsStack.push(news);
|
||||||
|
} finally {
|
||||||
|
writeLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public News read() {
|
||||||
|
News news;
|
||||||
|
try {
|
||||||
|
readLock.lock();
|
||||||
|
news = newsStack.peek();
|
||||||
|
} finally {
|
||||||
|
readLock.unlock();
|
||||||
|
}
|
||||||
|
return news;
|
||||||
|
}
|
||||||
|
}
|
34
src/exercises/ex_n/TestingReentrantReadWriteLock_News.java
Normal file
34
src/exercises/ex_n/TestingReentrantReadWriteLock_News.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package exercises.ex_n;
|
||||||
|
|
||||||
|
public class TestingReentrantReadWriteLock_News {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
NewsFeed newsFeed = new NewsFeed();
|
||||||
|
newsFeed.put(new News("START OF NEWS"));
|
||||||
|
|
||||||
|
// Create one writing thread
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (int i=0;i<200;i++) {
|
||||||
|
newsFeed.put(new News("News " + i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
// Create several reading threads
|
||||||
|
for (int i=0; i<20;i++) {
|
||||||
|
new Thread((new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (int i=0;i<20;i++) {
|
||||||
|
News news = newsFeed.read();
|
||||||
|
if (news != null) {
|
||||||
|
System.out.println("News read : "
|
||||||
|
+ newsFeed.read());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
75
src/exercises/ex_n_bis/LibraryCatalog.java
Normal file
75
src/exercises/ex_n_bis/LibraryCatalog.java
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
package exercises.ex_n_bis;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
|
public class LibraryCatalog {
|
||||||
|
private final Map<String, String> catalog = new HashMap<>();
|
||||||
|
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||||
|
private final Lock readLock = lock.readLock();
|
||||||
|
private final Lock writeLock = lock.writeLock();
|
||||||
|
|
||||||
|
public LibraryCatalog() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Book> getBooks() {
|
||||||
|
ArrayList<Book> books = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
readLock.lock();
|
||||||
|
catalog.forEach((title, author) -> {
|
||||||
|
books.add(new Book(title, author));
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
readLock.unlock();
|
||||||
|
}
|
||||||
|
return books;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String findBook(String title) {
|
||||||
|
String author;
|
||||||
|
try {
|
||||||
|
readLock.lock();
|
||||||
|
author = catalog.get(title);
|
||||||
|
} finally {
|
||||||
|
readLock.unlock();
|
||||||
|
}
|
||||||
|
if (author == null) {
|
||||||
|
System.out.println("The book '" + title + "' is not in the catalog");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addBook(String title, String author) {
|
||||||
|
try {
|
||||||
|
writeLock.lock();
|
||||||
|
catalog.put(title, author);
|
||||||
|
} finally {
|
||||||
|
writeLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeBook(String title) {
|
||||||
|
try {
|
||||||
|
writeLock.lock();
|
||||||
|
catalog.remove(title);
|
||||||
|
} finally {
|
||||||
|
writeLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateBook(String title, String newAuthor) {
|
||||||
|
try {
|
||||||
|
writeLock.lock();
|
||||||
|
catalog.replace(title, newAuthor);
|
||||||
|
} finally {
|
||||||
|
writeLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Book(String title, String author) {}
|
||||||
|
}
|
51
src/exercises/ex_o/LockedWithConditionsStack.java
Normal file
51
src/exercises/ex_o/LockedWithConditionsStack.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package exercises.ex_o;
|
||||||
|
|
||||||
|
import java.util.Stack;
|
||||||
|
import java.util.concurrent.locks.Condition;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
public class LockedWithConditionsStack {
|
||||||
|
private final int capacity;
|
||||||
|
private final Stack<Integer> stack = new Stack<>();
|
||||||
|
private final ReentrantLock lock = new ReentrantLock();
|
||||||
|
private final Condition fullCondition = lock.newCondition();
|
||||||
|
private final Condition emptyCondition = lock.newCondition();
|
||||||
|
|
||||||
|
public LockedWithConditionsStack(int capacity) {
|
||||||
|
this.capacity = capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pushToStack(int value) {
|
||||||
|
try {
|
||||||
|
lock.lock();
|
||||||
|
while (stack.size() == capacity) {
|
||||||
|
System.out.println("Stack is full, waiting until someone pops");
|
||||||
|
fullCondition.await();
|
||||||
|
}
|
||||||
|
stack.push(value);
|
||||||
|
emptyCondition.signalAll();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int popFromStack() {
|
||||||
|
int value;
|
||||||
|
try {
|
||||||
|
lock.lock();
|
||||||
|
while (stack.isEmpty()) {
|
||||||
|
System.out.println("Stack is empty, waiting until someone pushes");
|
||||||
|
emptyCondition.await();
|
||||||
|
}
|
||||||
|
value = stack.pop();
|
||||||
|
fullCondition.signalAll();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
16
src/exercises/ex_o/NumberConsumer.java
Normal file
16
src/exercises/ex_o/NumberConsumer.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package exercises.ex_o;
|
||||||
|
|
||||||
|
public class NumberConsumer implements Runnable {
|
||||||
|
private LockedWithConditionsStack stack;
|
||||||
|
|
||||||
|
public NumberConsumer(LockedWithConditionsStack stack) {
|
||||||
|
this.stack = stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
System.out.println("Pop from stack: " + stack.popFromStack());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
src/exercises/ex_o/NumberProducer.java
Normal file
17
src/exercises/ex_o/NumberProducer.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package exercises.ex_o;
|
||||||
|
|
||||||
|
public class NumberProducer implements Runnable {
|
||||||
|
private LockedWithConditionsStack stack;
|
||||||
|
public NumberProducer(LockedWithConditionsStack stack) {
|
||||||
|
this.stack = stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
System.out.println("Pushing to stack " + i + "...");
|
||||||
|
stack.pushToStack(i);
|
||||||
|
System.out.println("Pushed to stack " + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package exercises.ex_o;
|
||||||
|
|
||||||
|
public class TestingReentrantLockWithConditions {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
LockedWithConditionsStack stack = new LockedWithConditionsStack(5);
|
||||||
|
(new Thread(new NumberProducer(stack))).start();
|
||||||
|
(new Thread(new NumberConsumer(stack))).start();
|
||||||
|
}
|
||||||
|
}
|
13
src/exercises/ex_p/Drum.java
Normal file
13
src/exercises/ex_p/Drum.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package exercises.ex_p;
|
||||||
|
|
||||||
|
public class Drum {
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public Drum(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void play() {
|
||||||
|
System.out.println("Playing " + name);
|
||||||
|
}
|
||||||
|
}
|
38
src/exercises/ex_p/Partition.java
Normal file
38
src/exercises/ex_p/Partition.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package exercises.ex_p;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class Partition {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Drum bassDrum = new Drum("Bass Drum");
|
||||||
|
Drum floortom = new Drum("Floor Tom");
|
||||||
|
Drum snareDrum = new Drum("Snare Drum");
|
||||||
|
Drum rackTom = new Drum("Rack Tom");
|
||||||
|
Drum hiHat = new Drum("Hi-Hat");
|
||||||
|
Drum crashCymbal = new Drum("Crash Cymbal");
|
||||||
|
Drum rideCymbal = new Drum("Ride Cymbal");
|
||||||
|
Drum splashCymbal = new Drum("Splash Cymbal");
|
||||||
|
Drum chinaCymbal = new Drum("China Cymbal");
|
||||||
|
ScheduledExecutorService executor = Executors.newScheduledThreadPool(9);
|
||||||
|
int initialDelay = 1000;
|
||||||
|
int quaver = 500; // croche
|
||||||
|
int crotchet = 1000; // noire
|
||||||
|
int minim = 2000; // blanche
|
||||||
|
TimeUnit unit = TimeUnit.MILLISECONDS;
|
||||||
|
|
||||||
|
Drum[] drums = {
|
||||||
|
bassDrum, floortom, snareDrum,
|
||||||
|
rackTom, hiHat, crashCymbal,
|
||||||
|
rideCymbal, splashCymbal, chinaCymbal
|
||||||
|
};
|
||||||
|
int[] notes = {quaver, crotchet, minim};
|
||||||
|
|
||||||
|
for (int i=0; i < 9; i++) {
|
||||||
|
Drum drum = drums[i];
|
||||||
|
int rhythm = notes[(int) (Math.random() * 3)];
|
||||||
|
executor.scheduleAtFixedRate(drum::play, initialDelay, rhythm, unit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
src/exercises/ex_p_bis/Ansi.java
Normal file
13
src/exercises/ex_p_bis/Ansi.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package exercises.ex_p_bis;
|
||||||
|
|
||||||
|
public class Ansi {
|
||||||
|
public static final String RESET = "\u001B[0m";
|
||||||
|
public static final String BLACK = "\u001B[30m";
|
||||||
|
public static final String RED = "\u001B[31m";
|
||||||
|
public static final String GREEN = "\u001B[32m";
|
||||||
|
public static final String YELLOW = "\u001B[33m";
|
||||||
|
public static final String BLUE = "\u001B[34m";
|
||||||
|
public static final String PURPLE = "\u001B[35m";
|
||||||
|
public static final String CYAN = "\u001B[36m";
|
||||||
|
public static final String WHITE = "\u001B[37m";
|
||||||
|
}
|
51
src/exercises/ex_p_bis/ChristmasTree.java
Normal file
51
src/exercises/ex_p_bis/ChristmasTree.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package exercises.ex_p_bis;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ChristmasTree {
|
||||||
|
private static final String[] lines = {
|
||||||
|
" ★ ★ ★",
|
||||||
|
" ★ ╱╲ ",
|
||||||
|
" ★ ╱ ╲ ★ ",
|
||||||
|
" ╱ ╲ ",
|
||||||
|
" ★ ╱ ╲ ★ ",
|
||||||
|
" ╱ ╲ ",
|
||||||
|
" ╱─ ─╲ ",
|
||||||
|
" ╱ ╲ ★ ",
|
||||||
|
" ★ ╱ ╲ ",
|
||||||
|
" ╱────┐ ┌────╲ ",
|
||||||
|
" ★ │ │ ★ ",
|
||||||
|
};
|
||||||
|
public static final int W = 20;
|
||||||
|
public static final int H = 11;
|
||||||
|
private final Map<Integer, Light> lights = new HashMap<>();
|
||||||
|
|
||||||
|
public void addLight(int x, int y, Light light) {
|
||||||
|
lights.put(x + y * W, light);
|
||||||
|
light.setTree(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void show() {
|
||||||
|
String result = "";
|
||||||
|
for (int y=0; y < H; y++) {
|
||||||
|
String line = "";
|
||||||
|
for (int x=0; x < W; x++) {
|
||||||
|
String c = String.valueOf(lines[y].charAt(x));
|
||||||
|
if (c.equals("★")) {
|
||||||
|
c = Ansi.YELLOW + c + Ansi.RESET;
|
||||||
|
}
|
||||||
|
Light light = lights.get(x + y * W);
|
||||||
|
if (light != null) {
|
||||||
|
c = light.apply(c);
|
||||||
|
}
|
||||||
|
line += c;
|
||||||
|
}
|
||||||
|
if (y != 0) {
|
||||||
|
result += "\n";
|
||||||
|
}
|
||||||
|
result += line;
|
||||||
|
}
|
||||||
|
System.out.println(result);
|
||||||
|
}
|
||||||
|
}
|
32
src/exercises/ex_p_bis/ChristmasTreeTester.java
Normal file
32
src/exercises/ex_p_bis/ChristmasTreeTester.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package exercises.ex_p_bis;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class ChristmasTreeTester {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ChristmasTree tree = new ChristmasTree();
|
||||||
|
|
||||||
|
Light light1 = new Light(Ansi.RED);
|
||||||
|
Light light2 = new Light(Ansi.RED);
|
||||||
|
Light light3 = new Light(Ansi.GREEN);
|
||||||
|
Light light4 = new Light(Ansi.GREEN);
|
||||||
|
Light light5 = new Light(Ansi.WHITE);
|
||||||
|
Light light6 = new Light(Ansi.WHITE);
|
||||||
|
|
||||||
|
tree.addLight(8, 3, light1);
|
||||||
|
tree.addLight(11, 5, light2);
|
||||||
|
tree.addLight(13, 6, light3);
|
||||||
|
tree.addLight(6, 7, light4);
|
||||||
|
tree.addLight(10, 2, light5);
|
||||||
|
tree.addLight(12, 8, light6);
|
||||||
|
|
||||||
|
ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
|
||||||
|
Light[] lights = {light1, light2, light3, light4, light5, light6};
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
Light light = lights[i];
|
||||||
|
executor.scheduleAtFixedRate(light::toggle, 0, (long) (1000 + Math.random() * 2000), TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
src/exercises/ex_p_bis/Light.java
Normal file
31
src/exercises/ex_p_bis/Light.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package exercises.ex_p_bis;
|
||||||
|
|
||||||
|
public class Light {
|
||||||
|
private boolean isOn = false;
|
||||||
|
private String prefix = "";
|
||||||
|
private static final String suffix = Ansi.RESET;
|
||||||
|
private ChristmasTree tree;
|
||||||
|
|
||||||
|
public Light(String prefix) {
|
||||||
|
this.prefix = prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggle() {
|
||||||
|
isOn = !isOn;
|
||||||
|
tree.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTree(ChristmasTree tree) {
|
||||||
|
this.tree = tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String apply(String c) {
|
||||||
|
if (isOn) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
if (c.equals(" ")) {
|
||||||
|
c = "⬤";
|
||||||
|
}
|
||||||
|
return prefix + c + suffix;
|
||||||
|
}
|
||||||
|
}
|
13
src/exercises/ex_q1/Pizza.java
Normal file
13
src/exercises/ex_q1/Pizza.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package exercises.ex_q1;
|
||||||
|
|
||||||
|
public class Pizza {
|
||||||
|
public void prepare() {
|
||||||
|
System.out.println("Preparing pizza.");
|
||||||
|
}
|
||||||
|
public void bake() {
|
||||||
|
System.out.println("Baking pizza.");
|
||||||
|
}
|
||||||
|
public void cut() {
|
||||||
|
System.out.println("Cutting pizza.");
|
||||||
|
}
|
||||||
|
}
|
34
src/exercises/ex_q1/Pizzaiolo.java
Normal file
34
src/exercises/ex_q1/Pizzaiolo.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package exercises.ex_q1;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
public class Pizzaiolo implements Callable<Pizza> {
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public Pizzaiolo(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void serve(Pizza pizza) {
|
||||||
|
System.out.println(name + "'s pizza is ready: pizza " + pizza.hashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pizza makePizza() throws InterruptedException {
|
||||||
|
Pizza pizza = new Pizza();
|
||||||
|
pizza.prepare();
|
||||||
|
Thread.sleep(200);
|
||||||
|
pizza.bake();
|
||||||
|
Thread.sleep(300);
|
||||||
|
pizza.cut();
|
||||||
|
Thread.sleep(100);
|
||||||
|
return pizza;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pizza call() throws Exception {
|
||||||
|
System.out.println("Thread " + name + " started by the executor");
|
||||||
|
Pizza pizza = makePizza();
|
||||||
|
System.out.println("Thread " + name + " pizza finished");
|
||||||
|
return pizza;
|
||||||
|
}
|
||||||
|
}
|
26
src/exercises/ex_q1/Pizzeria.java
Normal file
26
src/exercises/ex_q1/Pizzeria.java
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package exercises.ex_q1;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
|
||||||
|
public class Pizzeria {
|
||||||
|
public static void main(String[] args) throws ExecutionException, InterruptedException {
|
||||||
|
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
Pizzaiolo marco = new Pizzaiolo("Marco");
|
||||||
|
Pizzaiolo antonio = new Pizzaiolo("Antonio");
|
||||||
|
|
||||||
|
Future<Pizza> future1 = executor.submit(marco);
|
||||||
|
Future<Pizza> future2 = executor.submit(antonio);
|
||||||
|
Future<Pizza> future3 = executor.submit(marco);
|
||||||
|
Future<Pizza> future4 = executor.submit(antonio);
|
||||||
|
|
||||||
|
marco.serve(future1.get());
|
||||||
|
antonio.serve(future2.get());
|
||||||
|
marco.serve(future3.get());
|
||||||
|
antonio.serve(future4.get());
|
||||||
|
|
||||||
|
executor.shutdown();
|
||||||
|
}
|
||||||
|
}
|
34
src/exercises/ex_q2/CustomRecursiveAction.java
Normal file
34
src/exercises/ex_q2/CustomRecursiveAction.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package exercises.ex_q2;
|
||||||
|
|
||||||
|
import java.util.concurrent.RecursiveAction;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class CustomRecursiveAction extends RecursiveAction {
|
||||||
|
private static final int threshold = 10;
|
||||||
|
private String song;
|
||||||
|
|
||||||
|
public CustomRecursiveAction(String song) {
|
||||||
|
this.song = song;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void compute() {
|
||||||
|
Logger logger = Logger.getAnonymousLogger();
|
||||||
|
if (song.length() <= threshold) {
|
||||||
|
logger.info("Splitting problem");
|
||||||
|
changeToUppercase();
|
||||||
|
} else {
|
||||||
|
logger.info("Problem is small enough");
|
||||||
|
int halfSize = song.length() / 2;
|
||||||
|
CustomRecursiveAction task1 = new CustomRecursiveAction(song.substring(0, halfSize));
|
||||||
|
CustomRecursiveAction task2 = new CustomRecursiveAction(song.substring(halfSize));
|
||||||
|
invokeAll(task1, task2);
|
||||||
|
song = task1.song + task2.song;
|
||||||
|
logger.info("Solution: " + song);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void changeToUppercase() {
|
||||||
|
song = song.toUpperCase();
|
||||||
|
}
|
||||||
|
}
|
28
src/exercises/ex_q2/ForkJoinTest.java
Normal file
28
src/exercises/ex_q2/ForkJoinTest.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package exercises.ex_q2;
|
||||||
|
|
||||||
|
import java.util.concurrent.ForkJoinPool;
|
||||||
|
|
||||||
|
public class ForkJoinTest {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
String song = "Georges Brassens (1964) - Les Copains d'abord"
|
||||||
|
+ "Non, ce n'était pas le radeau"
|
||||||
|
+ "De la Méduse, ce bateau"
|
||||||
|
+ "Qu'on se le dise au fond des ports"
|
||||||
|
+ "Dise au fond des ports"
|
||||||
|
+ "Il naviguait en père peinard"
|
||||||
|
+ "Sur la grand-mare des canards"
|
||||||
|
+ "Et s'appelait les Copains d'abord"
|
||||||
|
+ "Les Copains d'abord";
|
||||||
|
int processors = Runtime.getRuntime().availableProcessors();
|
||||||
|
System.out.println("Number of available processors: " + processors);
|
||||||
|
ForkJoinPool pool = new ForkJoinPool(processors);
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
pool.invoke(new CustomRecursiveAction(song));
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
System.out.println(
|
||||||
|
"Fork/Join tasks took "
|
||||||
|
+ (endTime - startTime)
|
||||||
|
+ " milliseconds."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
8
src/exercises/ex_q3/Book.java
Normal file
8
src/exercises/ex_q3/Book.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package exercises.ex_q3;
|
||||||
|
|
||||||
|
public record Book(String ISBN, String title, String authorFirstName, String authorLastName, int year) implements Comparable<Book> {
|
||||||
|
@Override
|
||||||
|
public int compareTo(Book o) {
|
||||||
|
return title.compareTo(o.title);
|
||||||
|
}
|
||||||
|
}
|
67
src/exercises/ex_q3/BookGenerator.java
Normal file
67
src/exercises/ex_q3/BookGenerator.java
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package exercises.ex_q3;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BookGenerator {
|
||||||
|
private static final String[] adjectives = {
|
||||||
|
"big", "red", "small", "weird", "amazing", "fantastic", "friendly", "curious", "frightening",
|
||||||
|
};
|
||||||
|
private static final String[] nouns = {
|
||||||
|
"apple", "car", "gingerbread man", "octopus", "planet", "volcano", "bottle", "adventure"
|
||||||
|
};
|
||||||
|
private static final String[] determinants = {"the", "a"};
|
||||||
|
private static final String vowels = "aeiou";
|
||||||
|
|
||||||
|
private static final String[] firstnames = {
|
||||||
|
"John", "Patrick", "Gérard", "Jean-Michel", "Ronswalle", "Guilherme", "Jean-Claude", "Perceval", "Hector", "Ferguson",
|
||||||
|
"Azénor", "Clémentine", "Ailizabette", "Bérangère", "Clothilde", "Mélissandre"
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final String[] lastnames = {
|
||||||
|
"de Mont-Castel", "Smith", "Martin", "Ferguson", "Lassalle", "Berset", "Constantin"
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final Random random = new Random();
|
||||||
|
|
||||||
|
private static String getRandom(String[] list) {
|
||||||
|
int i = random.nextInt(list.length);
|
||||||
|
return list[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Book generateRandomBook() {
|
||||||
|
String noun = getRandom(nouns);
|
||||||
|
String adj = getRandom(adjectives);
|
||||||
|
String det = getRandom(determinants);
|
||||||
|
if (det.equals("a") && vowels.contains(adj.substring(0, 1))) {
|
||||||
|
det += "n";
|
||||||
|
}
|
||||||
|
String title = det + " " + adj + " " + noun;
|
||||||
|
title = title.substring(0, 1).toUpperCase() + title.substring(1);
|
||||||
|
|
||||||
|
String isbn = "";
|
||||||
|
int checksum = 0;
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
int digit = random.nextInt(10);
|
||||||
|
isbn += String.valueOf(digit);
|
||||||
|
if (i % 4 == 0) {
|
||||||
|
isbn += "-";
|
||||||
|
}
|
||||||
|
checksum += (10 - i) * digit;
|
||||||
|
}
|
||||||
|
checksum = checksum % 11;
|
||||||
|
if (checksum != 0) {
|
||||||
|
checksum = 11 - checksum;
|
||||||
|
}
|
||||||
|
if (checksum == 10) {
|
||||||
|
isbn += "X";
|
||||||
|
} else {
|
||||||
|
isbn += String.valueOf(checksum);
|
||||||
|
}
|
||||||
|
|
||||||
|
String firstname = getRandom(firstnames);
|
||||||
|
String lastname = getRandom(lastnames);
|
||||||
|
|
||||||
|
return new Book(isbn, title, firstname, lastname, random.nextInt(1000, 2025));
|
||||||
|
}
|
||||||
|
}
|
20
src/exercises/ex_q3/Library.java
Normal file
20
src/exercises/ex_q3/Library.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package exercises.ex_q3;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class Library {
|
||||||
|
private static final int SIZE = 100_000;
|
||||||
|
private static final Book[] books = new Book[SIZE];
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
for (int i = 0; i < SIZE; i++) {
|
||||||
|
Book book = BookGenerator.generateRandomBook();
|
||||||
|
books[i] = book;
|
||||||
|
}
|
||||||
|
|
||||||
|
Arrays.parallelSort(books);
|
||||||
|
for (int i = 0; i < Math.min(15, SIZE); i++) {
|
||||||
|
System.out.println(books[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
src/exercises/ex_r/Customer.java
Normal file
28
src/exercises/ex_r/Customer.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package exercises.ex_r;
|
||||||
|
|
||||||
|
public class Customer implements Runnable {
|
||||||
|
private String name;
|
||||||
|
private PostOffice office;
|
||||||
|
|
||||||
|
public Customer(String name, PostOffice office) {
|
||||||
|
this.name = name;
|
||||||
|
this.office = office;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
Package pkg = new Package(this);
|
||||||
|
office.registerPackage(pkg);
|
||||||
|
try {
|
||||||
|
Thread.sleep((long) (1000L + 5000L * Math.random()));
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
src/exercises/ex_r/Package.java
Normal file
15
src/exercises/ex_r/Package.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package exercises.ex_r;
|
||||||
|
|
||||||
|
public class Package {
|
||||||
|
private Customer sender;
|
||||||
|
public Package(Customer sender) {
|
||||||
|
this.sender = sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Package{" +
|
||||||
|
"sender=" + sender.getName() +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
19
src/exercises/ex_r/PostOffice.java
Normal file
19
src/exercises/ex_r/PostOffice.java
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package exercises.ex_r;
|
||||||
|
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
public class PostOffice {
|
||||||
|
private BlockingQueue<Package> packages = new LinkedBlockingQueue<>();
|
||||||
|
|
||||||
|
public void registerPackage(Package pkg) {
|
||||||
|
packages.add(pkg);
|
||||||
|
System.out.println("Registered " + pkg + " (now " + packages.size() + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Package takePackage() throws InterruptedException {
|
||||||
|
Package pkg = packages.take();
|
||||||
|
System.out.println("Withdrawn " + pkg + " (now " + packages.size() + ")");
|
||||||
|
return pkg;
|
||||||
|
}
|
||||||
|
}
|
22
src/exercises/ex_r/Postman.java
Normal file
22
src/exercises/ex_r/Postman.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package exercises.ex_r;
|
||||||
|
|
||||||
|
public class Postman implements Runnable {
|
||||||
|
private PostOffice office;
|
||||||
|
|
||||||
|
public Postman(PostOffice office) {
|
||||||
|
this.office = office;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
Package pkg = office.takePackage();
|
||||||
|
Thread.sleep((long) (1000L + 2000L * Math.random()));
|
||||||
|
System.out.println("Delivered " + pkg);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
src/exercises/ex_r/TestingBlockingQueue_PostOffice.java
Normal file
10
src/exercises/ex_r/TestingBlockingQueue_PostOffice.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package exercises.ex_r;
|
||||||
|
|
||||||
|
public class TestingBlockingQueue_PostOffice {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
PostOffice postOffice = new PostOffice();
|
||||||
|
(new Thread(new Postman(postOffice))).start();
|
||||||
|
(new Thread(new Customer("Mrs Darbellay", postOffice))).start();
|
||||||
|
(new Thread(new Customer("Mrs Müller", postOffice))).start();
|
||||||
|
}
|
||||||
|
}
|
33
src/exercises/ex_s1/Cow.java
Normal file
33
src/exercises/ex_s1/Cow.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package exercises.ex_s1;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class Cow implements Runnable {
|
||||||
|
private String name;
|
||||||
|
private ConcurrentHashMap<String, Integer> stalls;
|
||||||
|
private final Random random = new Random();
|
||||||
|
|
||||||
|
public Cow(String name, ConcurrentHashMap<String, Integer> stalls) {
|
||||||
|
this.name = name;
|
||||||
|
this.stalls = stalls;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
Thread.sleep((long) (1000L + Math.random() * 5000L));
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
String key = "box" + random.nextInt(1, 4);
|
||||||
|
Integer units = stalls.replace(key, 0);
|
||||||
|
if (units == null || units == 0) {
|
||||||
|
System.out.println(name + " ate nothing");
|
||||||
|
} else {
|
||||||
|
System.out.println(name + " ate " + units + " units of food from " + key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
src/exercises/ex_s1/Farmer.java
Normal file
30
src/exercises/ex_s1/Farmer.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package exercises.ex_s1;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class Farmer implements Runnable {
|
||||||
|
private String name;
|
||||||
|
private ConcurrentHashMap<String, Integer> stalls;
|
||||||
|
private final Random random = new Random();
|
||||||
|
|
||||||
|
public Farmer(String name, ConcurrentHashMap<String, Integer> stalls) {
|
||||||
|
this.name = name;
|
||||||
|
this.stalls = stalls;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
Thread.sleep((long) (1000L + Math.random() * 2000L));
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
String key = "box" + random.nextInt(1, 4);
|
||||||
|
int units = random.nextInt(10, 100);
|
||||||
|
stalls.put(key, units);
|
||||||
|
System.out.println(name + " puts " + units + " units of food in " + key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
src/exercises/ex_s1/TestingConcurrentHashMap_Farm.java
Normal file
14
src/exercises/ex_s1/TestingConcurrentHashMap_Farm.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package exercises.ex_s1;
|
||||||
|
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class TestingConcurrentHashMap_Farm {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ConcurrentHashMap<String, Integer> animalStallMap = new ConcurrentHashMap<>();
|
||||||
|
new Thread(new Farmer("Verena", animalStallMap)).start();
|
||||||
|
new Thread(new Farmer("Pierre", animalStallMap)).start();
|
||||||
|
for (int i = 1; i < 10; i++) {
|
||||||
|
new Thread(new Cow("Cow" + i, animalStallMap)).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
42
src/exercises/ex_s2/TestingAtomicInteger.java
Normal file
42
src/exercises/ex_s2/TestingAtomicInteger.java
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package exercises.ex_s2;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicIntegerArray;
|
||||||
|
|
||||||
|
public class TestingAtomicInteger {
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
int[] nonAtomic = new int[5];
|
||||||
|
AtomicIntegerArray atomic = new AtomicIntegerArray(5);
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
nonAtomic[i] = i;
|
||||||
|
atomic.set(i, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Starting values atomic array: " + atomic);
|
||||||
|
System.out.println("Starting values of non atomic array: " + Arrays.toString(nonAtomic));
|
||||||
|
System.out.println("Creating 3 threads to increment the values within those two arrays");
|
||||||
|
|
||||||
|
Thread[] threads = new Thread[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
threads[i] = new Thread(() -> {
|
||||||
|
for (int j = 0; j < 100000; j++) {
|
||||||
|
for (int k = 0; k < 5; k++) {
|
||||||
|
nonAtomic[k] += 1;
|
||||||
|
atomic.incrementAndGet(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
threads[i].start();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
threads[i].join();
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Final values atomic array: " + atomic);
|
||||||
|
System.out.println("Final values of non atomic array: " + Arrays.toString(nonAtomic));
|
||||||
|
}
|
||||||
|
}
|
20
src/exercises/ex_s3/AbstractTweet.java
Normal file
20
src/exercises/ex_s3/AbstractTweet.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package exercises.ex_s3;
|
||||||
|
|
||||||
|
public abstract class AbstractTweet {
|
||||||
|
private String author;
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
public AbstractTweet(String author, String content) {
|
||||||
|
this.author = author;
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void addLike();
|
||||||
|
public abstract void removeLike();
|
||||||
|
public abstract long getLikes();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "@" + author + " tweeted \"" + content + "\" (" + getLikes() + " likes)";
|
||||||
|
}
|
||||||
|
}
|
27
src/exercises/ex_s3/AtomicTweet.java
Normal file
27
src/exercises/ex_s3/AtomicTweet.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package exercises.ex_s3;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
public class AtomicTweet extends AbstractTweet {
|
||||||
|
|
||||||
|
private AtomicLong likes = new AtomicLong(0);
|
||||||
|
|
||||||
|
public AtomicTweet(String author, String content) {
|
||||||
|
super(author, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addLike() {
|
||||||
|
likes.incrementAndGet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeLike() {
|
||||||
|
likes.updateAndGet(i -> i > 0 ? i - 1 : i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLikes() {
|
||||||
|
return likes.get();
|
||||||
|
}
|
||||||
|
}
|
32
src/exercises/ex_s3/TestingAtomicLong.java
Normal file
32
src/exercises/ex_s3/TestingAtomicLong.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package exercises.ex_s3;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TestingAtomicLong {
|
||||||
|
public static String[] names = {
|
||||||
|
"Alice", "Bob", "Charlie", "Derek", "Emily",
|
||||||
|
"Fionna", "Greg", "Harry", "Isabella", "Julia"
|
||||||
|
};
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
List<AbstractTweet> tweets = new ArrayList<>();
|
||||||
|
AbstractTweet tweet1 = new Tweet("Alice", "Java is cool !");
|
||||||
|
AbstractTweet tweet2 = new AtomicTweet("Bob", "ISC is the best !");
|
||||||
|
tweets.add(tweet1);
|
||||||
|
tweets.add(tweet2);
|
||||||
|
|
||||||
|
Thread[] users = new Thread[10];
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
users[i] = new Thread(new User(names[i], tweets));
|
||||||
|
users[i].start();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
users[i].join();
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(tweet1);
|
||||||
|
System.out.println(tweet2);
|
||||||
|
}
|
||||||
|
}
|
21
src/exercises/ex_s3/Tweet.java
Normal file
21
src/exercises/ex_s3/Tweet.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package exercises.ex_s3;
|
||||||
|
|
||||||
|
public class Tweet extends AbstractTweet {
|
||||||
|
private long likes = 0;
|
||||||
|
|
||||||
|
public Tweet(String author, String content) {
|
||||||
|
super(author, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addLike() {
|
||||||
|
likes += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeLike() {
|
||||||
|
likes -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLikes() {
|
||||||
|
return likes;
|
||||||
|
}
|
||||||
|
}
|
24
src/exercises/ex_s3/User.java
Normal file
24
src/exercises/ex_s3/User.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package exercises.ex_s3;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class User implements Runnable {
|
||||||
|
private final String name;
|
||||||
|
private final List<AbstractTweet> tweets;
|
||||||
|
|
||||||
|
public User(String name, List<AbstractTweet> tweets) {
|
||||||
|
this.name = name;
|
||||||
|
this.tweets = tweets;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (int i = 0; i < 100000; i++) {
|
||||||
|
if (i % 10 == 9) {
|
||||||
|
tweets.forEach(AbstractTweet::removeLike);
|
||||||
|
} else {
|
||||||
|
tweets.forEach(AbstractTweet::addLike);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
src/exercises/ex_t/BowlSemaphore.java
Normal file
24
src/exercises/ex_t/BowlSemaphore.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package exercises.ex_t;
|
||||||
|
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
|
public class BowlSemaphore {
|
||||||
|
private boolean isFull = false;
|
||||||
|
private Semaphore semaphore = new Semaphore(1);
|
||||||
|
|
||||||
|
public boolean fill() throws InterruptedException {
|
||||||
|
semaphore.acquire();
|
||||||
|
boolean wasFull = isFull;
|
||||||
|
isFull = true;
|
||||||
|
semaphore.release();
|
||||||
|
return wasFull;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean empty() throws InterruptedException {
|
||||||
|
semaphore.acquire();
|
||||||
|
boolean wasFull = isFull;
|
||||||
|
isFull = false;
|
||||||
|
semaphore.release();
|
||||||
|
return wasFull;
|
||||||
|
}
|
||||||
|
}
|
29
src/exercises/ex_t/Dog.java
Normal file
29
src/exercises/ex_t/Dog.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package exercises.ex_t;
|
||||||
|
|
||||||
|
import exercises.Utils;
|
||||||
|
|
||||||
|
public class Dog implements Runnable {
|
||||||
|
private final String name;
|
||||||
|
private final BowlSemaphore[] bowls;
|
||||||
|
|
||||||
|
public Dog(String name, BowlSemaphore[] bowls) {
|
||||||
|
this.name = name;
|
||||||
|
this.bowls = bowls;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
BowlSemaphore bowl = bowls[i];
|
||||||
|
try {
|
||||||
|
if (bowl.empty()) {
|
||||||
|
System.out.println(name + " ate from bowl " + i);
|
||||||
|
Utils.randomSleep(10000, 20000);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (InterruptedException _) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
src/exercises/ex_t/Feeder.java
Normal file
28
src/exercises/ex_t/Feeder.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package exercises.ex_t;
|
||||||
|
|
||||||
|
import exercises.Utils;
|
||||||
|
|
||||||
|
public class Feeder implements Runnable {
|
||||||
|
private final String name;
|
||||||
|
private final BowlSemaphore[] bowls;
|
||||||
|
|
||||||
|
public Feeder(String name, BowlSemaphore[] bowls) {
|
||||||
|
this.name = name;
|
||||||
|
this.bowls = bowls;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
BowlSemaphore bowl = bowls[i];
|
||||||
|
try {
|
||||||
|
if (!bowl.fill()) {
|
||||||
|
System.out.println(name + " filled bowl " + i);
|
||||||
|
Utils.randomSleep(1000, 3000);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException _) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
src/exercises/ex_t/TestingSemaphore_DogBreeder.java
Normal file
16
src/exercises/ex_t/TestingSemaphore_DogBreeder.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package exercises.ex_t;
|
||||||
|
|
||||||
|
public class TestingSemaphore_DogBreeder {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
BowlSemaphore[] bowlsSemaphores = new BowlSemaphore[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
bowlsSemaphores[i] = new BowlSemaphore();
|
||||||
|
}
|
||||||
|
|
||||||
|
new Thread(new Feeder("Marco", bowlsSemaphores)).start();
|
||||||
|
new Thread(new Feeder("Luisa", bowlsSemaphores)).start();
|
||||||
|
for (int i = 1; i < 10; i++) {
|
||||||
|
new Thread(new Dog("Dog" + i, bowlsSemaphores)).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
src/exercises/ex_u/FamilyMember.java
Normal file
22
src/exercises/ex_u/FamilyMember.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package exercises.ex_u;
|
||||||
|
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
|
public class FamilyMember implements Runnable {
|
||||||
|
private final String name;
|
||||||
|
private final Vehicle vehicle;
|
||||||
|
private final CountDownLatch countDownLatch;
|
||||||
|
|
||||||
|
public FamilyMember(String name, Vehicle vehicle, CountDownLatch countDownLatch) {
|
||||||
|
this.name = name;
|
||||||
|
this.vehicle = vehicle;
|
||||||
|
this.countDownLatch = countDownLatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
vehicle.addSuitcase(name + "'s suitcase");
|
||||||
|
System.out.println(name + " has loaded their suitcase");
|
||||||
|
countDownLatch.countDown();
|
||||||
|
}
|
||||||
|
}
|
23
src/exercises/ex_u/TestingCountDownLatch_FamilyTrip.java
Normal file
23
src/exercises/ex_u/TestingCountDownLatch_FamilyTrip.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package exercises.ex_u;
|
||||||
|
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
|
public class TestingCountDownLatch_FamilyTrip {
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
Vehicle seatAlhambra = new Vehicle();
|
||||||
|
seatAlhambra.printVehicleContent();
|
||||||
|
String[] family = {"Jean", "Anna", "Joseph", "Martha", "Eleonore", "Paul", "Catarina"};
|
||||||
|
// Create a countDownLatch
|
||||||
|
CountDownLatch countDownLatch = new CountDownLatch(family.length);
|
||||||
|
|
||||||
|
// Start the family members
|
||||||
|
// and synchronize them before the start
|
||||||
|
for (int i = 0; i < family.length; i++) {
|
||||||
|
new Thread(new FamilyMember(family[i], seatAlhambra, countDownLatch)).start();
|
||||||
|
}
|
||||||
|
countDownLatch.await();
|
||||||
|
|
||||||
|
seatAlhambra.printVehicleContent();
|
||||||
|
System.out.println("Family trip can start");
|
||||||
|
}
|
||||||
|
}
|
14
src/exercises/ex_u/Vehicle.java
Normal file
14
src/exercises/ex_u/Vehicle.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package exercises.ex_u;
|
||||||
|
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
|
public class Vehicle {
|
||||||
|
private Queue<String> suitcases = new ConcurrentLinkedQueue<>();
|
||||||
|
public void addSuitcase(String suitcase) {
|
||||||
|
suitcases.add(suitcase);
|
||||||
|
}
|
||||||
|
public void printVehicleContent() {
|
||||||
|
System.out.println("Suitcases: " + suitcases);
|
||||||
|
}
|
||||||
|
}
|
20
src/exercises/ex_v/Referee.java
Normal file
20
src/exercises/ex_v/Referee.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package exercises.ex_v;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Referee implements Runnable {
|
||||||
|
private final List<Result> results;
|
||||||
|
|
||||||
|
public Referee(List<Result> results) {
|
||||||
|
this.results = results;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
System.out.println("Referee starts to establish ranking...");
|
||||||
|
results.sort(Result::compareTo);
|
||||||
|
System.out.println("PDG Team Ranking:");
|
||||||
|
results.forEach(System.out::println);
|
||||||
|
}
|
||||||
|
}
|
28
src/exercises/ex_v/Result.java
Normal file
28
src/exercises/ex_v/Result.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package exercises.ex_v;
|
||||||
|
|
||||||
|
public class Result implements Comparable<Result>{
|
||||||
|
private final int time;
|
||||||
|
private final String team;
|
||||||
|
public Result(String team, int time) {
|
||||||
|
this.time = time;
|
||||||
|
this.team = team;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTime() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTeam() {
|
||||||
|
return team;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Result result) {
|
||||||
|
return this.getTime() - result.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getTeam() + " : " + getTime() + "h";
|
||||||
|
}
|
||||||
|
}
|
34
src/exercises/ex_v/Team.java
Normal file
34
src/exercises/ex_v/Team.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package exercises.ex_v;
|
||||||
|
|
||||||
|
import exercises.Utils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.BrokenBarrierException;
|
||||||
|
import java.util.concurrent.CyclicBarrier;
|
||||||
|
|
||||||
|
public class Team implements Runnable {
|
||||||
|
private final String name;
|
||||||
|
private final List<Result> results;
|
||||||
|
private final CyclicBarrier barrier;
|
||||||
|
|
||||||
|
public Team(int i, List<Result> results, CyclicBarrier barrier) {
|
||||||
|
this.name = "Team " + i;
|
||||||
|
this.results = results;
|
||||||
|
this.barrier = barrier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
System.out.println(name + " : Started the race");
|
||||||
|
try {
|
||||||
|
Utils.randomSleep(1000, 5000);
|
||||||
|
} catch (InterruptedException _) {}
|
||||||
|
|
||||||
|
Result result = new Result(name, (int) (Math.random() * 20 + 1));
|
||||||
|
System.out.println(name + " : Finished the race in " + result.getTime() + " hours and is waiting for other teams");
|
||||||
|
results.add(result);
|
||||||
|
try {
|
||||||
|
barrier.await();
|
||||||
|
} catch (InterruptedException | BrokenBarrierException _) {}
|
||||||
|
}
|
||||||
|
}
|
22
src/exercises/ex_v/TestingCyclicBarrier_PDG.java
Normal file
22
src/exercises/ex_v/TestingCyclicBarrier_PDG.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package exercises.ex_v;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.BrokenBarrierException;
|
||||||
|
import java.util.concurrent.CyclicBarrier;
|
||||||
|
|
||||||
|
public class TestingCyclicBarrier_PDG {
|
||||||
|
private static int NUM_TEAMS = 20;
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Result> results = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
System.out.println("Starting PDG with " + NUM_TEAMS + " teams ");
|
||||||
|
CyclicBarrier barrier = new CyclicBarrier(NUM_TEAMS, new Referee(results));
|
||||||
|
|
||||||
|
// Start the team threads and synchronize them.
|
||||||
|
// Make sure finally to order to order the results and print them
|
||||||
|
for (int i = 0; i < NUM_TEAMS; i++) {
|
||||||
|
new Thread(new Team(i, results, barrier)).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
src/exercises/ex_w/Car.java
Normal file
19
src/exercises/ex_w/Car.java
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package exercises.ex_w;
|
||||||
|
|
||||||
|
public class Car {
|
||||||
|
private String name;
|
||||||
|
private String licensePlateNumber;
|
||||||
|
public Car(String name, String licensePlateNumber) {
|
||||||
|
this.name = name;
|
||||||
|
this.licensePlateNumber = licensePlateNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLicensePlateNumber() {
|
||||||
|
return licensePlateNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
18
src/exercises/ex_w/Customer.java
Normal file
18
src/exercises/ex_w/Customer.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package exercises.ex_w;
|
||||||
|
|
||||||
|
public class Customer implements Runnable {
|
||||||
|
private final String name;
|
||||||
|
private final String licensePlateNumber;
|
||||||
|
private Car car;
|
||||||
|
|
||||||
|
public Customer(String name, Car car) {
|
||||||
|
this.name = name;
|
||||||
|
this.car = car;
|
||||||
|
licensePlateNumber = car.getLicensePlateNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
33
src/exercises/ex_w/Garage.java
Normal file
33
src/exercises/ex_w/Garage.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package exercises.ex_w;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Exchanger;
|
||||||
|
|
||||||
|
public class Garage implements Runnable {
|
||||||
|
private List<Car> courtesyCars = new ArrayList<>();
|
||||||
|
private Exchanger<Car> receiveExchanger = new Exchanger<>();
|
||||||
|
|
||||||
|
public Garage() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Car leaveForRepair(Car car) throws InterruptedException {
|
||||||
|
return receiveExchanger.exchange(car);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
Car courtesyCar = courtesyCars.removeFirst();
|
||||||
|
try {
|
||||||
|
Car toRepair = receiveExchanger.exchange(courtesyCar);
|
||||||
|
|
||||||
|
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
src/exercises/ex_w/TestingExchanger_Garage.java
Normal file
12
src/exercises/ex_w/TestingExchanger_Garage.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package exercises.ex_w;
|
||||||
|
|
||||||
|
public class TestingExchanger_Garage {
|
||||||
|
String[] carTypes = {"Seat Alhambra", "BMW Mini", "Tesla 3"};
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// Create a Customer thread and a Garage thread
|
||||||
|
// that use an exchanger for replacing the customer car
|
||||||
|
// with a courtesy car during the reparation. At the end of the day,
|
||||||
|
// the cars are exchanged back.
|
||||||
|
Garage garage = new Garage();
|
||||||
|
}
|
||||||
|
}
|
35
src/exercises/ex_x/FamilyMember.java
Normal file
35
src/exercises/ex_x/FamilyMember.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package exercises.ex_x;
|
||||||
|
|
||||||
|
import exercises.Utils;
|
||||||
|
|
||||||
|
import java.util.concurrent.Phaser;
|
||||||
|
|
||||||
|
public class FamilyMember implements Runnable {
|
||||||
|
private final String name;
|
||||||
|
private final Phaser phaser;
|
||||||
|
private final int numSteps;
|
||||||
|
|
||||||
|
public FamilyMember(String name, Phaser phaser, int numSteps) {
|
||||||
|
this.name = name;
|
||||||
|
this.phaser = phaser;
|
||||||
|
this.numSteps = numSteps;
|
||||||
|
phaser.register();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
int step = 0;
|
||||||
|
while (step < numSteps) {
|
||||||
|
step = phaser.getPhase() + 1;
|
||||||
|
try {
|
||||||
|
System.out.println(name + ": Step " + step + " started");
|
||||||
|
Utils.randomSleep(1000, 3000);
|
||||||
|
phaser.arriveAndAwaitAdvance();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
phaser.arriveAndDeregister();
|
||||||
|
System.out.println(name + " has arrived");
|
||||||
|
}
|
||||||
|
}
|
24
src/exercises/ex_x/TestingPhaserFamilyBikeTrip.java
Normal file
24
src/exercises/ex_x/TestingPhaserFamilyBikeTrip.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package exercises.ex_x;
|
||||||
|
|
||||||
|
import java.util.concurrent.Phaser;
|
||||||
|
|
||||||
|
public class TestingPhaserFamilyBikeTrip {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
String[] family = {"Father", "Mother", "Son", "Daughter_1", "Daughter_2"};
|
||||||
|
String[] routes = {"Sierre", "Sion", "Martigny", "St-Maurice", "Aigle", "Vevey"};
|
||||||
|
Phaser phaser = new Phaser();
|
||||||
|
phaser.register();
|
||||||
|
|
||||||
|
System.out.println("The family leaves Brig for a bike trip to Vevey");
|
||||||
|
for (int i = 0; i < family.length; i++) {
|
||||||
|
new Thread(new FamilyMember(family[i], phaser, routes.length)).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < routes.length; i++) {
|
||||||
|
phaser.arriveAndAwaitAdvance();
|
||||||
|
System.out.println("All family members arrived to " + routes[i]);
|
||||||
|
}
|
||||||
|
phaser.arriveAndDeregister();
|
||||||
|
System.out.println("End of the bike trip.");
|
||||||
|
}
|
||||||
|
}
|
21
src/exercises/ex_y/RaceTester.java
Normal file
21
src/exercises/ex_y/RaceTester.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package exercises.ex_y;
|
||||||
|
|
||||||
|
import java.util.concurrent.Phaser;
|
||||||
|
|
||||||
|
public class RaceTester {
|
||||||
|
public static final int NUM_RUNNERS = 10;
|
||||||
|
public static final int NUM_STAGES = 5;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
Phaser phaser = new Phaser();
|
||||||
|
phaser.register();
|
||||||
|
for (int i = 0; i < NUM_RUNNERS; i++) {
|
||||||
|
new Thread(new Runner(NUM_STAGES, phaser)).start();
|
||||||
|
}
|
||||||
|
for (int i = 0; i <= NUM_STAGES; i++) {
|
||||||
|
phaser.arriveAndAwaitAdvance();
|
||||||
|
}
|
||||||
|
System.out.println("Finished race");
|
||||||
|
phaser.arriveAndDeregister();
|
||||||
|
}
|
||||||
|
}
|
43
src/exercises/ex_y/Runner.java
Normal file
43
src/exercises/ex_y/Runner.java
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package exercises.ex_y;
|
||||||
|
|
||||||
|
import exercises.Utils;
|
||||||
|
|
||||||
|
import java.util.concurrent.Phaser;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
public class Runner implements Runnable {
|
||||||
|
private static AtomicInteger nextId = new AtomicInteger(0);
|
||||||
|
private final int id;
|
||||||
|
private final int maxStep;
|
||||||
|
private final Phaser phaser;
|
||||||
|
|
||||||
|
public Runner(int maxStep, Phaser phaser) {
|
||||||
|
id = nextId.getAndIncrement();
|
||||||
|
this.maxStep = maxStep;
|
||||||
|
this.phaser = phaser;
|
||||||
|
phaser.register();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
System.out.println(this + " is on the starting line");
|
||||||
|
phaser.arriveAndAwaitAdvance();
|
||||||
|
|
||||||
|
while (phaser.getPhase() <= this.maxStep) {
|
||||||
|
System.out.println(this + " started stage " + phaser.getPhase());
|
||||||
|
try {
|
||||||
|
Utils.randomSleep(1000, 5000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
System.out.println(this + " finished stage " + phaser.getPhase());
|
||||||
|
phaser.arriveAndAwaitAdvance();
|
||||||
|
}
|
||||||
|
phaser.arriveAndDeregister();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Runner " + id;
|
||||||
|
}
|
||||||
|
}
|
1
src/exercises/ex_y/answers.txt
Normal file
1
src/exercises/ex_y/answers.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
We should use a Phaser as it allows for threads to wait on each other before moving to the next step
|
26
src/exercises/ex_z4/AuctionMain.java
Normal file
26
src/exercises/ex_z4/AuctionMain.java
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package exercises.ex_z4;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
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) {
|
||||||
|
Auctioneer auctioneer = new Auctioneer("Paul", new ArrayList(Arrays.stream(items).toList()));
|
||||||
|
new Thread(auctioneer).start();
|
||||||
|
for (int i = 0; i < names.length; i++) {
|
||||||
|
new Thread(new Bidder(names[i], auctioneer)).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
src/exercises/ex_z4/AuctionState.java
Normal file
8
src/exercises/ex_z4/AuctionState.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package exercises.ex_z4;
|
||||||
|
|
||||||
|
public enum AuctionState {
|
||||||
|
PRESENTING_ITEM,
|
||||||
|
BIDDING,
|
||||||
|
SOLD,
|
||||||
|
FINISHED
|
||||||
|
}
|
161
src/exercises/ex_z4/Auctioneer.java
Normal file
161
src/exercises/ex_z4/Auctioneer.java
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
package exercises.ex_z4;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
import java.util.concurrent.locks.Condition;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
import static exercises.ex_z4.AuctionState.*;
|
||||||
|
|
||||||
|
public class Auctioneer implements Runnable {
|
||||||
|
private static final DecimalFormat df = new DecimalFormat("#.00");
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final Queue<Bid> bids = new ConcurrentLinkedQueue<>();
|
||||||
|
private final ArrayList<Item> items;
|
||||||
|
private final Lock bidLock = new ReentrantLock();
|
||||||
|
private final Condition bidCond = bidLock.newCondition();
|
||||||
|
public final Lock stateLock = new ReentrantLock();
|
||||||
|
public final Condition stateCond = stateLock.newCondition();
|
||||||
|
|
||||||
|
private Bid maximumBid;
|
||||||
|
private Thread countdownThread = null;
|
||||||
|
private AuctionState auctionState = PRESENTING_ITEM;
|
||||||
|
|
||||||
|
|
||||||
|
public Auctioneer(String name, ArrayList<Item> items) {
|
||||||
|
this.name = name;
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void announce(String msg) {
|
||||||
|
System.out.println("[Auctioneer " + name + "] " + msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setState(AuctionState newState) {
|
||||||
|
stateLock.lock();
|
||||||
|
try {
|
||||||
|
auctionState = newState;
|
||||||
|
stateCond.signalAll();
|
||||||
|
} finally {
|
||||||
|
stateLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 !");
|
||||||
|
maximumBid = null;
|
||||||
|
setState(BIDDING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void placeBid(Bid bid) {
|
||||||
|
if (auctionState == BIDDING) {
|
||||||
|
System.out.println(bid.bidder() + " bids $" + df.format(bid.amount()));
|
||||||
|
bidLock.lock();
|
||||||
|
try {
|
||||||
|
bids.add(bid);
|
||||||
|
bidCond.signalAll();
|
||||||
|
} finally {
|
||||||
|
bidLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void countdown() {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
System.out.println("Three");
|
||||||
|
Thread.sleep(1000);
|
||||||
|
System.out.println("Two");
|
||||||
|
Thread.sleep(1000);
|
||||||
|
System.out.println("One");
|
||||||
|
Thread.sleep(1000);
|
||||||
|
setState(SOLD);
|
||||||
|
bidLock.lock();
|
||||||
|
try {
|
||||||
|
bidCond.signalAll();
|
||||||
|
} finally {
|
||||||
|
bidLock.unlock();
|
||||||
|
}
|
||||||
|
} catch (InterruptedException _) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startCountdown() {
|
||||||
|
countdownThread = new Thread(this::countdown);
|
||||||
|
countdownThread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bid getMaximumBid() {
|
||||||
|
return maximumBid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuctionState getAuctionState() {
|
||||||
|
return auctionState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finalizeBidding() throws InterruptedException {
|
||||||
|
if (maximumBid == null) {
|
||||||
|
announce("Nobody wants this items ?!");
|
||||||
|
} else {
|
||||||
|
announce("And sold for $" + df.format(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()) {
|
||||||
|
setState(FINISHED);
|
||||||
|
} else {
|
||||||
|
setState(PRESENTING_ITEM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (auctionState != FINISHED) {
|
||||||
|
try {
|
||||||
|
switch (auctionState) {
|
||||||
|
case PRESENTING_ITEM -> {
|
||||||
|
presentItem();
|
||||||
|
}
|
||||||
|
case BIDDING -> {
|
||||||
|
Bid current_bid = bids.poll();
|
||||||
|
if (current_bid == null) {
|
||||||
|
if (maximumBid != null) {
|
||||||
|
startCountdown();
|
||||||
|
}
|
||||||
|
bidLock.lock();
|
||||||
|
try {
|
||||||
|
bidCond.await();
|
||||||
|
} finally {
|
||||||
|
bidLock.unlock();
|
||||||
|
}
|
||||||
|
if (countdownThread != null) {
|
||||||
|
countdownThread.interrupt();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (maximumBid == null || current_bid.amount() > maximumBid.amount()) {
|
||||||
|
maximumBid = current_bid;
|
||||||
|
announce("New best bid : " + df.format(maximumBid.amount()) + " by " + maximumBid.bidder());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case SOLD -> {
|
||||||
|
finalizeBidding();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
announce("The auction is now finished ! Thank you for participating !");
|
||||||
|
}
|
||||||
|
}
|
5
src/exercises/ex_z4/Bid.java
Normal file
5
src/exercises/ex_z4/Bid.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package exercises.ex_z4;
|
||||||
|
|
||||||
|
public record Bid(Bidder bidder, double amount) {
|
||||||
|
|
||||||
|
}
|
78
src/exercises/ex_z4/Bidder.java
Normal file
78
src/exercises/ex_z4/Bidder.java
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
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<Item> items = new ArrayList<>();
|
||||||
|
private Double lastBid = null;
|
||||||
|
private final Auctioneer auctioneer;
|
||||||
|
|
||||||
|
public Bidder(String name, Auctioneer auctioneer) {
|
||||||
|
this.name = name;
|
||||||
|
this.id = nextId++;
|
||||||
|
this.auctioneer = auctioneer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
AuctionState state = auctioneer.getAuctionState();
|
||||||
|
if (state == BIDDING) {
|
||||||
|
Random rand = new Random();
|
||||||
|
double addon = rand.nextDouble(500);
|
||||||
|
Bid maximumBid = auctioneer.getMaximumBid();
|
||||||
|
double base = maximumBid == null ? 0 : maximumBid.amount();
|
||||||
|
lastBid = base + addon;
|
||||||
|
auctioneer.placeBid(new Bid(this, lastBid));
|
||||||
|
long minSleep = (long) (base * 10);
|
||||||
|
try {
|
||||||
|
Utils.randomSleep(minSleep, minSleep + 1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
} else if (state == FINISHED) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
auctioneer.stateLock.lock();
|
||||||
|
try {
|
||||||
|
auctioneer.stateCond.await();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
auctioneer.stateLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addItem(Item item){
|
||||||
|
items.add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getLastBid() {
|
||||||
|
return lastBid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "(" + id + ") " + name;
|
||||||
|
}
|
||||||
|
}
|
5
src/exercises/ex_z4/Item.java
Normal file
5
src/exercises/ex_z4/Item.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package exercises.ex_z4;
|
||||||
|
|
||||||
|
public record Item(String name) {
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user