mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-05-28 10:23:52 +00:00
deps: Refactor dependencies (#3224)
* remove spring dep move junit, logging, mockito under dep mgmt * upgrade anti-corruption-layer deps * async method invocation * balking, bloc * bridge to bytecode * caching * callback - cqrs * component - health check * hexagonal - metadata mapping * rest of the patterns * remove checkstyle, take spotless into use
This commit is contained in:
@@ -35,10 +35,9 @@ import lombok.extern.slf4j.Slf4j;
|
||||
* lock. Only if the locking criterion check indicates that locking is required does the actual
|
||||
* locking logic proceed.
|
||||
*
|
||||
* <p>In {@link Inventory} we store the items with a given size. However, we do not store more
|
||||
* items than the inventory size. To address concurrent access problems we use double checked
|
||||
* locking to add item to inventory. In this method, the thread which gets the lock first adds the
|
||||
* item.
|
||||
* <p>In {@link Inventory} we store the items with a given size. However, we do not store more items
|
||||
* than the inventory size. To address concurrent access problems we use double checked locking to
|
||||
* add item to inventory. In this method, the thread which gets the lock first adds the item.
|
||||
*/
|
||||
@Slf4j
|
||||
public class App {
|
||||
@@ -51,11 +50,15 @@ public class App {
|
||||
public static void main(String[] args) {
|
||||
final var inventory = new Inventory(1000);
|
||||
var executorService = Executors.newFixedThreadPool(3);
|
||||
IntStream.range(0, 3).<Runnable>mapToObj(i -> () -> {
|
||||
while (inventory.addItem(new Item())) {
|
||||
LOGGER.info("Adding another item");
|
||||
}
|
||||
}).forEach(executorService::execute);
|
||||
IntStream.range(0, 3)
|
||||
.<Runnable>mapToObj(
|
||||
i ->
|
||||
() -> {
|
||||
while (inventory.addItem(new Item())) {
|
||||
LOGGER.info("Adding another item");
|
||||
}
|
||||
})
|
||||
.forEach(executorService::execute);
|
||||
|
||||
executorService.shutdown();
|
||||
try {
|
||||
|
||||
+3
-10
@@ -30,9 +30,7 @@ import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Inventory.
|
||||
*/
|
||||
/** Inventory. */
|
||||
@Slf4j
|
||||
public class Inventory {
|
||||
|
||||
@@ -40,18 +38,14 @@ public class Inventory {
|
||||
private final List<Item> items;
|
||||
private final Lock lock;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
/** Constructor. */
|
||||
public Inventory(int inventorySize) {
|
||||
this.inventorySize = inventorySize;
|
||||
this.items = new ArrayList<>(inventorySize);
|
||||
this.lock = new ReentrantLock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add item.
|
||||
*/
|
||||
/** Add item. */
|
||||
public boolean addItem(Item item) {
|
||||
if (items.size() < inventorySize) {
|
||||
lock.lock();
|
||||
@@ -77,5 +71,4 @@ public class Inventory {
|
||||
public final List<Item> getItems() {
|
||||
return List.copyOf(items);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,8 +24,5 @@
|
||||
*/
|
||||
package com.iluwatar.doublechecked.locking;
|
||||
|
||||
/**
|
||||
* Item.
|
||||
*/
|
||||
public class Item {
|
||||
}
|
||||
/** Item. */
|
||||
public class Item {}
|
||||
|
||||
+6
-11
@@ -24,24 +24,19 @@
|
||||
*/
|
||||
package com.iluwatar.doublechecked.locking;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
|
||||
/**
|
||||
* Application test
|
||||
*/
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Application test */
|
||||
class AppTest {
|
||||
|
||||
/**
|
||||
* Issue: Add at least one assertion to this test case.
|
||||
* Solution: Inserted assertion to check whether the execution of the main method in {@link App#main(String[])}
|
||||
* throws an exception.
|
||||
* Issue: Add at least one assertion to this test case. Solution: Inserted assertion to check
|
||||
* whether the execution of the main method in {@link App#main(String[])} throws an exception.
|
||||
*/
|
||||
|
||||
|
||||
@Test
|
||||
void shouldExecuteApplicationWithoutException() {
|
||||
assertDoesNotThrow(() -> App.main(new String[]{}));
|
||||
assertDoesNotThrow(() -> App.main(new String[] {}));
|
||||
}
|
||||
}
|
||||
|
||||
+32
-30
@@ -43,10 +43,7 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* InventoryTest
|
||||
*
|
||||
*/
|
||||
/** InventoryTest */
|
||||
class InventoryTest {
|
||||
|
||||
private InMemoryAppender appender;
|
||||
@@ -67,9 +64,7 @@ class InventoryTest {
|
||||
*/
|
||||
private static final int THREAD_COUNT = 8;
|
||||
|
||||
/**
|
||||
* The maximum number of {@link Item}s allowed in the {@link Inventory}
|
||||
*/
|
||||
/** The maximum number of {@link Item}s allowed in the {@link Inventory} */
|
||||
private static final int INVENTORY_SIZE = 1000;
|
||||
|
||||
/**
|
||||
@@ -80,34 +75,42 @@ class InventoryTest {
|
||||
*/
|
||||
@Test
|
||||
void testAddItem() {
|
||||
assertTimeout(ofMillis(10000), () -> {
|
||||
// Create a new inventory with a limit of 1000 items and put some load on the add method
|
||||
final var inventory = new Inventory(INVENTORY_SIZE);
|
||||
final var executorService = Executors.newFixedThreadPool(THREAD_COUNT);
|
||||
IntStream.range(0, THREAD_COUNT).<Runnable>mapToObj(i -> () -> {
|
||||
while (inventory.addItem(new Item())) ;
|
||||
}).forEach(executorService::execute);
|
||||
assertTimeout(
|
||||
ofMillis(10000),
|
||||
() -> {
|
||||
// Create a new inventory with a limit of 1000 items and put some load on the add method
|
||||
final var inventory = new Inventory(INVENTORY_SIZE);
|
||||
final var executorService = Executors.newFixedThreadPool(THREAD_COUNT);
|
||||
IntStream.range(0, THREAD_COUNT)
|
||||
.<Runnable>mapToObj(
|
||||
i ->
|
||||
() -> {
|
||||
while (inventory.addItem(new Item()))
|
||||
;
|
||||
})
|
||||
.forEach(executorService::execute);
|
||||
|
||||
// Wait until all threads have finished
|
||||
executorService.shutdown();
|
||||
executorService.awaitTermination(5, TimeUnit.SECONDS);
|
||||
// Wait until all threads have finished
|
||||
executorService.shutdown();
|
||||
executorService.awaitTermination(5, TimeUnit.SECONDS);
|
||||
|
||||
// Check the number of items in the inventory. It should not have exceeded the allowed maximum
|
||||
final var items = inventory.getItems();
|
||||
assertNotNull(items);
|
||||
assertEquals(INVENTORY_SIZE, items.size());
|
||||
// Check the number of items in the inventory. It should not have exceeded the allowed
|
||||
// maximum
|
||||
final var items = inventory.getItems();
|
||||
assertNotNull(items);
|
||||
assertEquals(INVENTORY_SIZE, items.size());
|
||||
|
||||
assertEquals(INVENTORY_SIZE, appender.getLogSize());
|
||||
assertEquals(INVENTORY_SIZE, appender.getLogSize());
|
||||
|
||||
// ... and check if the inventory size is increasing continuously
|
||||
IntStream.range(0, items.size())
|
||||
.mapToObj(i -> appender.log.get(i).getFormattedMessage()
|
||||
.contains("items.size()=" + (i + 1)))
|
||||
.forEach(Assertions::assertTrue);
|
||||
});
|
||||
// ... and check if the inventory size is increasing continuously
|
||||
IntStream.range(0, items.size())
|
||||
.mapToObj(
|
||||
i ->
|
||||
appender.log.get(i).getFormattedMessage().contains("items.size()=" + (i + 1)))
|
||||
.forEach(Assertions::assertTrue);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private static class InMemoryAppender extends AppenderBase<ILoggingEvent> {
|
||||
private final List<ILoggingEvent> log = new LinkedList<>();
|
||||
|
||||
@@ -125,5 +128,4 @@ class InventoryTest {
|
||||
return log.size();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user