java concurrency (#2502)

* fix spring config

* fix spring config

* fix spring config

* minor fix

* fix spring-boot module

* fix pom

* upgrade jackson

* minor fix

* java concurrency

* cleanup
This commit is contained in:
Doha2012
2017-08-27 12:14:26 +02:00
committed by Grzegorz Piwowarek
parent 09d10ac85f
commit 25263f1d6f
93 changed files with 362 additions and 44 deletions
@@ -1,34 +0,0 @@
package com.baeldung.concurrent.Scheduledexecutorservice;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorServiceDemo {
public void execute() {
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<?> scheduledFuture = executorService.schedule(() -> {
// Task
}, 1, TimeUnit.SECONDS);
executorService.scheduleAtFixedRate(() -> {
// Task
}, 1, 10, TimeUnit.SECONDS);
executorService.scheduleWithFixedDelay(() -> {
// Task
}, 1, 10, TimeUnit.SECONDS);
Future<String> future = executorService.schedule(() -> {
// Task
return "Hellow world";
}, 1, TimeUnit.SECONDS);
executorService.shutdown();
}
}
@@ -1,13 +0,0 @@
package com.baeldung.concurrent.atomic;
public class SafeCounterWithLock {
private volatile int counter;
public int getValue() {
return counter;
}
public synchronized void increment() {
counter++;
}
}
@@ -1,21 +0,0 @@
package com.baeldung.concurrent.atomic;
import java.util.concurrent.atomic.AtomicInteger;
public class SafeCounterWithoutLock {
private final AtomicInteger counter = new AtomicInteger(0);
public int getValue() {
return counter.get();
}
public void increment() {
while(true) {
int existingValue = getValue();
int newValue = existingValue + 1;
if(counter.compareAndSet(existingValue, newValue)) {
return;
}
}
}
}
@@ -1,13 +0,0 @@
package com.baeldung.concurrent.atomic;
public class UnsafeCounter {
int counter;
public int getValue() {
return counter;
}
public void increment() {
counter++;
}
}
@@ -1,24 +0,0 @@
package com.baeldung.concurrent.blockingqueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class BlockingQueueUsage {
public static void main(String[] args) {
int BOUND = 10;
int N_PRODUCERS = 4;
int N_CONSUMERS = Runtime.getRuntime().availableProcessors();
int poisonPill = Integer.MAX_VALUE;
int poisonPillPerProducer = N_CONSUMERS / N_PRODUCERS;
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(BOUND);
for (int i = 0; i < N_PRODUCERS; i++) {
new Thread(new NumbersProducer(queue, poisonPill, poisonPillPerProducer)).start();
}
for (int j = 0; j < N_CONSUMERS; j++) {
new Thread(new NumbersConsumer(queue, poisonPill)).start();
}
}
}
@@ -1,28 +0,0 @@
package com.baeldung.concurrent.blockingqueue;
import java.util.concurrent.BlockingQueue;
public class NumbersConsumer implements Runnable {
private final BlockingQueue<Integer> queue;
private final int poisonPill;
NumbersConsumer(BlockingQueue<Integer> queue, int poisonPill) {
this.queue = queue;
this.poisonPill = poisonPill;
}
public void run() {
try {
while (true) {
Integer number = queue.take();
if (number.equals(poisonPill)) {
return;
}
String result = number.toString();
System.out.println(Thread.currentThread().getName() + " result: " + result);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
@@ -1,36 +0,0 @@
package com.baeldung.concurrent.blockingqueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadLocalRandom;
public class NumbersProducer implements Runnable {
private final BlockingQueue<Integer> numbersQueue;
private final int poisonPill;
private final int poisonPillPerProducer;
NumbersProducer(BlockingQueue<Integer> numbersQueue, int poisonPill, int poisonPillPerProducer) {
this.numbersQueue = numbersQueue;
this.poisonPill = poisonPill;
this.poisonPillPerProducer = poisonPillPerProducer;
}
public void run() {
try {
generateNumbers();
} catch (InterruptedException e) {
Thread.currentThread()
.interrupt();
}
}
private void generateNumbers() throws InterruptedException {
for (int i = 0; i < 100; i++) {
numbersQueue.put(ThreadLocalRandom.current()
.nextInt(100));
}
for (int j = 0; j < poisonPillPerProducer; j++) {
numbersQueue.put(poisonPill);
}
}
}
@@ -1,23 +0,0 @@
package com.baeldung.concurrent.countdownlatch;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class BrokenWorker implements Runnable {
private final List<String> outputScraper;
private final CountDownLatch countDownLatch;
BrokenWorker(final List<String> outputScraper, final CountDownLatch countDownLatch) {
this.outputScraper = outputScraper;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
if (true) {
throw new RuntimeException("Oh dear");
}
countDownLatch.countDown();
outputScraper.add("Counted down");
}
}
@@ -1,34 +0,0 @@
package com.baeldung.concurrent.countdownlatch;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class WaitingWorker implements Runnable {
private final List<String> outputScraper;
private final CountDownLatch readyThreadCounter;
private final CountDownLatch callingThreadBlocker;
private final CountDownLatch completedThreadCounter;
WaitingWorker(final List<String> outputScraper, final CountDownLatch readyThreadCounter, final CountDownLatch callingThreadBlocker, CountDownLatch completedThreadCounter) {
this.outputScraper = outputScraper;
this.readyThreadCounter = readyThreadCounter;
this.callingThreadBlocker = callingThreadBlocker;
this.completedThreadCounter = completedThreadCounter;
}
@Override
public void run() {
// Mark this thread as read / started
readyThreadCounter.countDown();
try {
callingThreadBlocker.await();
outputScraper.add("Counted down");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
completedThreadCounter.countDown();
}
}
}
@@ -1,22 +0,0 @@
package com.baeldung.concurrent.countdownlatch;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class Worker implements Runnable {
private final List<String> outputScraper;
private final CountDownLatch countDownLatch;
Worker(final List<String> outputScraper, final CountDownLatch countDownLatch) {
this.outputScraper = outputScraper;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
// Do some work
System.out.println("Doing some logic");
outputScraper.add("Counted down");
countDownLatch.countDown();
}
}
@@ -1,77 +0,0 @@
package com.baeldung.concurrent.cyclicbarrier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
private CyclicBarrier cyclicBarrier;
private List<List<Integer>> partialResults = Collections.synchronizedList(new ArrayList<>());
private Random random = new Random();
private int NUM_PARTIAL_RESULTS;
private int NUM_WORKERS;
private void runSimulation(int numWorkers, int numberOfPartialResults) {
NUM_PARTIAL_RESULTS = numberOfPartialResults;
NUM_WORKERS = numWorkers;
cyclicBarrier = new CyclicBarrier(NUM_WORKERS, new AggregatorThread());
System.out.println("Spawning " + NUM_WORKERS + " worker threads to compute " + NUM_PARTIAL_RESULTS + " partial results each");
for (int i = 0; i < NUM_WORKERS; i++) {
Thread worker = new Thread(new NumberCruncherThread());
worker.setName("Thread " + i);
worker.start();
}
}
class NumberCruncherThread implements Runnable {
@Override
public void run() {
String thisThreadName = Thread.currentThread().getName();
List<Integer> partialResult = new ArrayList<>();
for (int i = 0; i < NUM_PARTIAL_RESULTS; i++) {
Integer num = random.nextInt(10);
System.out.println(thisThreadName + ": Crunching some numbers! Final result - " + num);
partialResult.add(num);
}
partialResults.add(partialResult);
try {
System.out.println(thisThreadName + " waiting for others to reach barrier.");
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
class AggregatorThread implements Runnable {
@Override
public void run() {
String thisThreadName = Thread.currentThread().getName();
System.out.println(thisThreadName + ": Computing final sum of " + NUM_WORKERS + " workers, having " + NUM_PARTIAL_RESULTS + " results each.");
int sum = 0;
for (List<Integer> threadResult : partialResults) {
System.out.print("Adding ");
for (Integer partialResult : threadResult) {
System.out.print(partialResult + " ");
sum += partialResult;
}
System.out.println();
}
System.out.println(Thread.currentThread().getName() + ": Final result = " + sum);
}
}
public static void main(String[] args) {
CyclicBarrierDemo play = new CyclicBarrierDemo();
play.runSimulation(5, 3);
}
}
@@ -1,24 +0,0 @@
package com.baeldung.concurrent.cyclicbarrier;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
public void start() {
CyclicBarrier cyclicBarrier = new CyclicBarrier(3, () -> {
// Task
System.out.println("All previous tasks are completed");
});
Thread t1 = new Thread(new Task(cyclicBarrier), "T1");
Thread t2 = new Thread(new Task(cyclicBarrier), "T2");
Thread t3 = new Thread(new Task(cyclicBarrier), "T3");
if (!cyclicBarrier.isBroken()) {
t1.start();
t2.start();
t3.start();
}
}
}
@@ -1,24 +0,0 @@
package com.baeldung.concurrent.cyclicbarrier;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class Task implements Runnable {
private CyclicBarrier barrier;
public Task(CyclicBarrier barrier) {
this.barrier = barrier;
}
@Override
public void run() {
try {
System.out.println("Thread : " + Thread.currentThread().getName() + " is waiting");
barrier.await();
System.out.println("Thread : " + Thread.currentThread().getName() + " is released");
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
@@ -1,32 +0,0 @@
package com.baeldung.concurrent.delayqueue;
import com.google.common.primitives.Ints;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public class DelayObject implements Delayed {
private String data;
private long startTime;
DelayObject(String data, long delayInMilliseconds) {
this.data = data;
this.startTime = System.currentTimeMillis() + delayInMilliseconds;
}
@Override
public long getDelay(TimeUnit unit) {
long diff = startTime - System.currentTimeMillis();
return unit.convert(diff, TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed o) {
return Ints.saturatedCast(this.startTime - ((DelayObject) o).startTime);
}
@Override
public String toString() {
return "{" + "data='" + data + '\'' + ", startTime=" + startTime + '}';
}
}
@@ -1,30 +0,0 @@
package com.baeldung.concurrent.delayqueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
public class DelayQueueConsumer implements Runnable {
private BlockingQueue<DelayObject> queue;
private final Integer numberOfElementsToTake;
final AtomicInteger numberOfConsumedElements = new AtomicInteger();
DelayQueueConsumer(BlockingQueue<DelayObject> queue, Integer numberOfElementsToTake) {
this.queue = queue;
this.numberOfElementsToTake = numberOfElementsToTake;
}
@Override
public void run() {
for (int i = 0; i < numberOfElementsToTake; i++) {
try {
DelayObject object = queue.take();
numberOfConsumedElements.incrementAndGet();
System.out.println("Consumer take: " + object);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@@ -1,34 +0,0 @@
package com.baeldung.concurrent.delayqueue;
import java.util.UUID;
import java.util.concurrent.BlockingQueue;
public class DelayQueueProducer implements Runnable {
private BlockingQueue<DelayObject> queue;
private final Integer numberOfElementsToProduce;
private final Integer delayOfEachProducedMessageMilliseconds;
DelayQueueProducer(BlockingQueue<DelayObject> queue,
Integer numberOfElementsToProduce,
Integer delayOfEachProducedMessageMilliseconds) {
this.queue = queue;
this.numberOfElementsToProduce = numberOfElementsToProduce;
this.delayOfEachProducedMessageMilliseconds = delayOfEachProducedMessageMilliseconds;
}
@Override
public void run() {
for (int i = 0; i < numberOfElementsToProduce; i++) {
DelayObject object
= new DelayObject(UUID.randomUUID().toString(), delayOfEachProducedMessageMilliseconds);
System.out.println("Put object = " + object);
try {
queue.put(object);
Thread.sleep(500);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}
@@ -1,29 +0,0 @@
package com.baeldung.concurrent.diningphilosophers;
public class DiningPhilosophers {
public static void main(String[] args) throws Exception {
Philosopher[] philosophers = new Philosopher[5];
Object[] forks = new Object[philosophers.length];
for (int i = 0; i < forks.length; i++) {
forks[i] = new Object();
}
for (int i = 0; i < philosophers.length; i++) {
Object leftFork = forks[i];
Object rightFork = forks[(i + 1) % forks.length];
if (i == philosophers.length - 1) {
philosophers[i] = new Philosopher(rightFork, leftFork); // The last philosopher picks up the right fork first
} else {
philosophers[i] = new Philosopher(leftFork, rightFork);
}
Thread t = new Thread(philosophers[i], "Philosopher " + (i + 1));
t.start();
}
}
}
@@ -1,36 +0,0 @@
package com.baeldung.concurrent.diningphilosophers;
public class Philosopher implements Runnable {
private final Object leftFork;
private final Object rightFork;
Philosopher(Object left, Object right) {
this.leftFork = left;
this.rightFork = right;
}
private void doAction(String action) throws InterruptedException {
System.out.println(Thread.currentThread().getName() + " " + action);
Thread.sleep(((int) (Math.random() * 100)));
}
@Override
public void run() {
try {
while (true) {
doAction(System.nanoTime() + ": Thinking"); // thinking
synchronized (leftFork) {
doAction(System.nanoTime() + ": Picked up left fork");
synchronized (rightFork) {
doAction(System.nanoTime() + ": Picked up right fork - eating"); // eating
doAction(System.nanoTime() + ": Put down right fork");
}
doAction(System.nanoTime() + ": Put down left fork. Returning to thinking");
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
@@ -1,14 +0,0 @@
package com.baeldung.concurrent.executor;
import java.util.concurrent.Executor;
public class ExecutorDemo {
public void execute() {
Executor executor = new Invoker();
executor.execute(()->{
// task to be performed
});
}
}
@@ -1,12 +0,0 @@
package com.baeldung.concurrent.executor;
import java.util.concurrent.Executor;
public class Invoker implements Executor {
@Override
public void execute(Runnable r) {
r.run();
}
}
@@ -1,27 +0,0 @@
package com.baeldung.concurrent.executorservice;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ExecutorServiceDemo {
ExecutorService executor = Executors.newFixedThreadPool(10);
public void execute() {
executor.submit(() -> {
new Task();
});
executor.shutdown();
executor.shutdownNow();
try {
executor.awaitTermination(20l, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@@ -1,10 +0,0 @@
package com.baeldung.concurrent.executorservice;
public class Task implements Runnable {
@Override
public void run() {
// task details
}
}
@@ -1,26 +0,0 @@
package com.baeldung.concurrent.future;
import java.util.concurrent.RecursiveTask;
public class FactorialSquareCalculator extends RecursiveTask<Integer> {
private static final long serialVersionUID = 1L;
final private Integer n;
FactorialSquareCalculator(Integer n) {
this.n = n;
}
@Override
protected Integer compute() {
if (n <= 1) {
return n;
}
FactorialSquareCalculator calculator = new FactorialSquareCalculator(n - 1);
calculator.fork();
return n * n + calculator.join();
}
}
@@ -1,44 +0,0 @@
package com.baeldung.concurrent.future;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class FutureDemo {
public String invoke() {
String str = null;
ExecutorService executorService = Executors.newFixedThreadPool(10);
Future<String> future = executorService.submit(() -> {
// Task
Thread.sleep(10000l);
return "Hellow world";
});
future.cancel(false);
try {
future.get(20, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e1) {
e1.printStackTrace();
}
if (future.isDone() && !future.isCancelled()) {
try {
str = future.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
return str;
}
}
@@ -1,20 +0,0 @@
package com.baeldung.concurrent.future;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
class SquareCalculator {
private final ExecutorService executor;
SquareCalculator(ExecutorService executor) {
this.executor = executor;
}
Future<Integer> calculate(Integer input) {
return executor.submit(() -> {
Thread.sleep(1000);
return input * input;
});
}
}
@@ -1,83 +0,0 @@
package com.baeldung.concurrent.locks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Stack;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import static java.lang.Thread.sleep;
public class ReentrantLockWithCondition {
private static Logger LOG = LoggerFactory.getLogger(ReentrantLockWithCondition.class);
private Stack<String> stack = new Stack<>();
private static final int CAPACITY = 5;
private ReentrantLock lock = new ReentrantLock();
private Condition stackEmptyCondition = lock.newCondition();
private Condition stackFullCondition = lock.newCondition();
private void pushToStack(String item) throws InterruptedException {
try {
lock.lock();
if (stack.size() == CAPACITY) {
LOG.info(Thread.currentThread().getName() + " wait on stack full");
stackFullCondition.await();
}
LOG.info("Pushing the item " + item);
stack.push(item);
stackEmptyCondition.signalAll();
} finally {
lock.unlock();
}
}
private String popFromStack() throws InterruptedException {
try {
lock.lock();
if (stack.size() == 0) {
LOG.info(Thread.currentThread().getName() + " wait on stack empty");
stackEmptyCondition.await();
}
return stack.pop();
} finally {
stackFullCondition.signalAll();
lock.unlock();
}
}
public static void main(String[] args) {
final int threadCount = 2;
ReentrantLockWithCondition object = new ReentrantLockWithCondition();
final ExecutorService service = Executors.newFixedThreadPool(threadCount);
service.execute(() -> {
for (int i = 0; i < 10; i++) {
try {
object.pushToStack("Item " + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
service.execute(() -> {
for (int i = 0; i < 10; i++) {
try {
LOG.info("Item popped " + object.popFromStack());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
service.shutdown();
}
}
@@ -1,88 +0,0 @@
package com.baeldung.concurrent.locks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import static java.lang.Thread.sleep;
public class SharedObjectWithLock {
private static final Logger LOG = LoggerFactory.getLogger(SharedObjectWithLock.class);
private ReentrantLock lock = new ReentrantLock(true);
private int counter = 0;
void perform() {
lock.lock();
LOG.info("Thread - " + Thread.currentThread().getName() + " acquired the lock");
try {
LOG.info("Thread - " + Thread.currentThread().getName() + " processing");
counter++;
} catch (Exception exception) {
LOG.error(" Interrupted Exception ", exception);
} finally {
lock.unlock();
LOG.info("Thread - " + Thread.currentThread().getName() + " released the lock");
}
}
private void performTryLock() {
LOG.info("Thread - " + Thread.currentThread().getName() + " attempting to acquire the lock");
try {
boolean isLockAcquired = lock.tryLock(2, TimeUnit.SECONDS);
if (isLockAcquired) {
try {
LOG.info("Thread - " + Thread.currentThread().getName() + " acquired the lock");
LOG.info("Thread - " + Thread.currentThread().getName() + " processing");
sleep(1000);
} finally {
lock.unlock();
LOG.info("Thread - " + Thread.currentThread().getName() + " released the lock");
}
}
} catch (InterruptedException exception) {
LOG.error(" Interrupted Exception ", exception);
}
LOG.info("Thread - " + Thread.currentThread().getName() + " could not acquire the lock");
}
public ReentrantLock getLock() {
return lock;
}
boolean isLocked() {
return lock.isLocked();
}
boolean hasQueuedThreads() {
return lock.hasQueuedThreads();
}
int getCounter() {
return counter;
}
public static void main(String[] args) {
final int threadCount = 2;
final ExecutorService service = Executors.newFixedThreadPool(threadCount);
final SharedObjectWithLock object = new SharedObjectWithLock();
service.execute(object::perform);
service.execute(object::performTryLock);
service.shutdown();
}
}
@@ -1,104 +0,0 @@
package com.baeldung.concurrent.locks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.StampedLock;
import static java.lang.Thread.sleep;
public class StampedLockDemo {
private Map<String, String> map = new HashMap<>();
private Logger logger = LoggerFactory.getLogger(StampedLockDemo.class);
private final StampedLock lock = new StampedLock();
public void put(String key, String value) throws InterruptedException {
long stamp = lock.writeLock();
try {
logger.info(Thread.currentThread().getName() + " acquired the write lock with stamp " + stamp);
map.put(key, value);
} finally {
lock.unlockWrite(stamp);
logger.info(Thread.currentThread().getName() + " unlocked the write lock with stamp " + stamp);
}
}
public String get(String key) throws InterruptedException {
long stamp = lock.readLock();
logger.info(Thread.currentThread().getName() + " acquired the read lock with stamp " + stamp);
try {
sleep(5000);
return map.get(key);
} finally {
lock.unlockRead(stamp);
logger.info(Thread.currentThread().getName() + " unlocked the read lock with stamp " + stamp);
}
}
private String readWithOptimisticLock(String key) throws InterruptedException {
long stamp = lock.tryOptimisticRead();
String value = map.get(key);
if (!lock.validate(stamp)) {
stamp = lock.readLock();
try {
sleep(5000);
return map.get(key);
} finally {
lock.unlock(stamp);
logger.info(Thread.currentThread().getName() + " unlocked the read lock with stamp " + stamp);
}
}
return value;
}
public static void main(String[] args) {
final int threadCount = 4;
final ExecutorService service = Executors.newFixedThreadPool(threadCount);
StampedLockDemo object = new StampedLockDemo();
Runnable writeTask = () -> {
try {
object.put("key1", "value1");
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Runnable readTask = () -> {
try {
object.get("key1");
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Runnable readOptimisticTask = () -> {
try {
object.readWithOptimisticLock("key1");
} catch (InterruptedException e) {
e.printStackTrace();
}
};
service.submit(writeTask);
service.submit(writeTask);
service.submit(readTask);
service.submit(readOptimisticTask);
service.shutdown();
}
}
@@ -1,120 +0,0 @@
package com.baeldung.concurrent.locks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import static java.lang.Thread.sleep;
public class SynchronizedHashMapWithRWLock {
private static Map<String, String> syncHashMap = new HashMap<>();
private Logger logger = LoggerFactory.getLogger(SynchronizedHashMapWithRWLock.class);
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock readLock = lock.readLock();
private final Lock writeLock = lock.writeLock();
public void put(String key, String value) throws InterruptedException {
try {
writeLock.lock();
logger.info(Thread.currentThread().getName() + " writing");
syncHashMap.put(key, value);
sleep(1000);
} finally {
writeLock.unlock();
}
}
public String get(String key) {
try {
readLock.lock();
logger.info(Thread.currentThread().getName() + " reading");
return syncHashMap.get(key);
} finally {
readLock.unlock();
}
}
public String remove(String key) {
try {
writeLock.lock();
return syncHashMap.remove(key);
} finally {
writeLock.unlock();
}
}
public boolean containsKey(String key) {
try {
readLock.lock();
return syncHashMap.containsKey(key);
} finally {
readLock.unlock();
}
}
boolean isReadLockAvailable() {
return readLock.tryLock();
}
public static void main(String[] args) throws InterruptedException {
final int threadCount = 3;
final ExecutorService service = Executors.newFixedThreadPool(threadCount);
SynchronizedHashMapWithRWLock object = new SynchronizedHashMapWithRWLock();
service.execute(new Thread(new Writer(object), "Writer"));
service.execute(new Thread(new Reader(object), "Reader1"));
service.execute(new Thread(new Reader(object), "Reader2"));
service.shutdown();
}
private static class Reader implements Runnable {
SynchronizedHashMapWithRWLock object;
Reader(SynchronizedHashMapWithRWLock object) {
this.object = object;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
object.get("key" + i);
}
}
}
private static class Writer implements Runnable {
SynchronizedHashMapWithRWLock object;
public Writer(SynchronizedHashMapWithRWLock object) {
this.object = object;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
object.put("key" + i, "value" + i);
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
@@ -1,27 +0,0 @@
package com.baeldung.concurrent.phaser;
import java.util.concurrent.Phaser;
class LongRunningAction implements Runnable {
private String threadName;
private Phaser ph;
LongRunningAction(String threadName, Phaser ph) {
this.threadName = threadName;
this.ph = ph;
ph.register();
}
@Override
public void run() {
System.out.println("This is phase " + ph.getPhase());
System.out.println("Thread " + threadName + " before long running action");
ph.arriveAndAwaitAdvance();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
ph.arriveAndDeregister();
}
}
@@ -1,22 +0,0 @@
package com.baeldung.concurrent.semaphore;
import java.util.concurrent.Semaphore;
public class SemaPhoreDemo {
static Semaphore semaphore = new Semaphore(10);
public void execute() throws InterruptedException {
System.out.println("Available permit : " + semaphore.availablePermits());
System.out.println("Number of threads waiting to acquire: " + semaphore.getQueueLength());
if (semaphore.tryAcquire()) {
semaphore.acquire();
// perform some critical operations
semaphore.release();
}
}
}
@@ -1,31 +0,0 @@
package com.baeldung.concurrent.semaphores;
import java.util.concurrent.Semaphore;
class CounterUsingMutex {
private final Semaphore mutex;
private int count;
CounterUsingMutex() {
mutex = new Semaphore(1);
count = 0;
}
void increase() throws InterruptedException {
mutex.acquire();
this.count = this.count + 1;
Thread.sleep(1000);
mutex.release();
}
int getCount() {
return this.count;
}
boolean hasQueuedThreads() {
return mutex.hasQueuedThreads();
}
}
@@ -1,23 +0,0 @@
package com.baeldung.concurrent.semaphores;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.concurrent.TimedSemaphore;
class DelayQueueUsingTimedSemaphore {
private final TimedSemaphore semaphore;
DelayQueueUsingTimedSemaphore(long period, int slotLimit) {
semaphore = new TimedSemaphore(period, TimeUnit.SECONDS, slotLimit);
}
boolean tryAdd() {
return semaphore.tryAcquire();
}
int availableSlots() {
return semaphore.getAvailablePermits();
}
}
@@ -1,25 +0,0 @@
package com.baeldung.concurrent.semaphores;
import java.util.concurrent.Semaphore;
class LoginQueueUsingSemaphore {
private final Semaphore semaphore;
LoginQueueUsingSemaphore(int slotLimit) {
semaphore = new Semaphore(slotLimit);
}
boolean tryLogin() {
return semaphore.tryAcquire();
}
void logout() {
semaphore.release();
}
int availableSlots() {
return semaphore.availablePermits();
}
}
@@ -1,21 +0,0 @@
package com.baeldung.concurrent.skiplist;
import java.time.ZonedDateTime;
class Event {
private final ZonedDateTime eventTime;
private final String content;
Event(ZonedDateTime eventTime, String content) {
this.eventTime = eventTime;
this.content = content;
}
ZonedDateTime getEventTime() {
return eventTime;
}
String getContent() {
return content;
}
}
@@ -1,29 +0,0 @@
package com.baeldung.concurrent.skiplist;
import java.time.ZonedDateTime;
import java.util.Comparator;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
class EventWindowSort {
private final ConcurrentSkipListMap<ZonedDateTime, String> events
= new ConcurrentSkipListMap<>(Comparator.comparingLong(value -> value.toInstant().toEpochMilli()));
void acceptEvent(Event event) {
events.put(event.getEventTime(), event.getContent());
}
ConcurrentNavigableMap<ZonedDateTime, String> getEventsFromLastMinute() {
return events.tailMap(ZonedDateTime
.now()
.minusMinutes(1));
}
ConcurrentNavigableMap<ZonedDateTime, String> getEventsOlderThatOneMinute() {
return events.headMap(ZonedDateTime
.now()
.minusMinutes(1));
}
}
@@ -1,27 +0,0 @@
package com.baeldung.concurrent.sleepwait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/***
* Example of waking up a waiting thread
*/
public class ThreadA {
private static final Logger LOG = LoggerFactory.getLogger(ThreadA.class);
private static final ThreadB b = new ThreadB();
public static void main(String... args) throws InterruptedException {
b.start();
synchronized (b) {
while (b.sum == 0) {
LOG.debug("Waiting for ThreadB to complete...");
b.wait();
}
LOG.debug("ThreadB has completed. Sum from that thread is: " + b.sum);
}
}
}
@@ -1,20 +0,0 @@
package com.baeldung.concurrent.sleepwait;
/***
* Example of waking up a waiting thread
*/
class ThreadB extends Thread {
int sum;
@Override
public void run() {
synchronized (this) {
int i = 0;
while (i < 100000) {
sum += i;
i++;
}
notify();
}
}
}
@@ -1,29 +0,0 @@
package com.baeldung.concurrent.sleepwait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/***
* Example of wait() and sleep() methods
*/
public class WaitSleepExample {
private static final Logger LOG = LoggerFactory.getLogger(WaitSleepExample.class);
private static final Object LOCK = new Object();
public static void main(String... args) throws InterruptedException {
sleepWaitInSynchronizedBlocks();
}
private static void sleepWaitInSynchronizedBlocks() throws InterruptedException {
Thread.sleep(1000); // called on the thread
LOG.debug("Thread '" + Thread.currentThread().getName() + "' is woken after sleeping for 1 second");
synchronized (LOCK) {
LOCK.wait(1000); // called on the object, synchronization required
LOG.debug("Object '" + LOCK + "' is woken after waiting for 1 second");
}
}
}
@@ -1,35 +0,0 @@
package com.baeldung.concurrent.synchronize;
public class BaeldungSynchronizedBlocks {
private int count = 0;
private static int staticCount = 0;
void performSynchronisedTask() {
synchronized (this) {
setCount(getCount() + 1);
}
}
static void performStaticSyncTask() {
synchronized (BaeldungSynchronizedBlocks.class) {
setStaticCount(getStaticCount() + 1);
}
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
static int getStaticCount() {
return staticCount;
}
private static void setStaticCount(int staticCount) {
BaeldungSynchronizedBlocks.staticCount = staticCount;
}
}
@@ -1,37 +0,0 @@
package com.baeldung.concurrent.synchronize;
public class BaeldungSynchronizedMethods {
private int sum = 0;
private int syncSum = 0;
static int staticSum = 0;
void calculate() {
setSum(getSum() + 1);
}
synchronized void synchronisedCalculate() {
setSyncSum(getSyncSum() + 1);
}
static synchronized void syncStaticCalculate() {
staticSum = staticSum + 1;
}
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
}
int getSyncSum() {
return syncSum;
}
private void setSyncSum(int syncSum) {
this.syncSum = syncSum;
}
}
@@ -1,23 +0,0 @@
package com.baeldung.concurrent.threadfactory;
import java.util.concurrent.ThreadFactory;
public class BaeldungThreadFactory implements ThreadFactory {
private int threadId;
private String name;
public BaeldungThreadFactory(String name) {
threadId = 1;
this.name = name;
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, name + "-Thread_" + threadId);
System.out.println("created new thread with id : " + threadId + " and name : " + t.getName());
threadId++;
return t;
}
}
@@ -1,13 +0,0 @@
package com.baeldung.concurrent.threadfactory;
public class Demo {
public void execute() {
BaeldungThreadFactory factory = new BaeldungThreadFactory("BaeldungThreadFactory");
for (int i = 0; i < 10; i++) {
Thread t = factory.newThread(new Task());
t.start();
}
}
}
@@ -1,10 +0,0 @@
package com.baeldung.concurrent.threadfactory;
public class Task implements Runnable {
@Override
public void run() {
// task details
}
}
@@ -1,13 +0,0 @@
package com.baeldung.concurrent.volatilekeyword;
public class SharedObject {
private volatile int count=0;
void increamentCount(){
count++;
}
public int getCount(){
return count;
}
}
@@ -1,17 +0,0 @@
package com.baeldung.threadlocal;
public class Context {
private final String userName;
public Context(String userName) {
this.userName = userName;
}
@Override
public String toString() {
return "Context{" +
"userNameSecret='" + userName + '\'' +
'}';
}
}
@@ -1,21 +0,0 @@
package com.baeldung.threadlocal;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class SharedMapWithUserContext implements Runnable {
public final static Map<Integer, Context> userContextPerUserId = new ConcurrentHashMap<>();
private final Integer userId;
private UserRepository userRepository = new UserRepository();
public SharedMapWithUserContext(Integer userId) {
this.userId = userId;
}
@Override
public void run() {
String userName = userRepository.getUserNameForUserId(userId);
userContextPerUserId.put(userId, new Context(userName));
}
}
@@ -1,24 +0,0 @@
package com.baeldung.threadlocal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ThreadLocalWithUserContext implements Runnable {
private static final Logger LOG = LoggerFactory.getLogger(ThreadLocalWithUserContext.class);
private static final ThreadLocal<Context> userContext = new ThreadLocal<>();
private final Integer userId;
private UserRepository userRepository = new UserRepository();
public ThreadLocalWithUserContext(Integer userId) {
this.userId = userId;
}
@Override
public void run() {
String userName = userRepository.getUserNameForUserId(userId);
userContext.set(new Context(userName));
LOG.debug("thread context for given userId: " + userId + " is: " + userContext.get());
}
}
@@ -1,10 +0,0 @@
package com.baeldung.threadlocal;
import java.util.UUID;
public class UserRepository {
public String getUserNameForUserId(Integer userId) {
return UUID.randomUUID().toString();
}
}
@@ -1,20 +0,0 @@
package com.baeldung.threadpool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.stream.Collectors;
public class CountingTask extends RecursiveTask<Integer> {
private final TreeNode node;
public CountingTask(TreeNode node) {
this.node = node;
}
@Override
protected Integer compute() {
return node.value + node.children.stream().map(childNode -> new CountingTask(childNode).fork()).collect(Collectors.summingInt(ForkJoinTask::join));
}
}
@@ -1,29 +0,0 @@
package com.baeldung.threadpool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import com.google.common.util.concurrent.MoreExecutors;
/**
* This class demonstrates the usage of Guava's exiting executor services that keep the VM from hanging.
* Without the exiting executor service, the task would hang indefinitely.
* This behaviour cannot be demonstrated in JUnit tests, as JUnit kills the VM after the tests.
*/
public class ExitingExecutorServiceExample {
public static void main(String... args) {
final ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(5);
final ExecutorService executorService = MoreExecutors.getExitingExecutorService(executor, 100, TimeUnit.MILLISECONDS);
executorService.submit((Runnable) () -> {
while (true) {
}
});
}
}
@@ -1,18 +0,0 @@
package com.baeldung.threadpool;
import java.util.Set;
import com.google.common.collect.Sets;
public class TreeNode {
int value;
Set<TreeNode> children;
public TreeNode(int value, TreeNode... children) {
this.value = value;
this.children = Sets.newHashSet(children);
}
}
@@ -1,41 +0,0 @@
package com.baeldung.transferqueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TransferQueue;
import java.util.concurrent.atomic.AtomicInteger;
public class Consumer implements Runnable {
private static final Logger LOG = LoggerFactory.getLogger(Consumer.class);
private final TransferQueue<String> transferQueue;
private final String name;
private final int numberOfMessagesToConsume;
public final AtomicInteger numberOfConsumedMessages = new AtomicInteger();
public Consumer(TransferQueue<String> transferQueue, String name, int numberOfMessagesToConsume) {
this.transferQueue = transferQueue;
this.name = name;
this.numberOfMessagesToConsume = numberOfMessagesToConsume;
}
@Override
public void run() {
for (int i = 0; i < numberOfMessagesToConsume; i++) {
try {
LOG.debug("Consumer: " + name + " is waiting to take element...");
String element = transferQueue.take();
longProcessing(element);
LOG.debug("Consumer: " + name + " received element: " + element);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void longProcessing(String element) throws InterruptedException {
numberOfConsumedMessages.incrementAndGet();
Thread.sleep(500);
}
}
@@ -1,41 +0,0 @@
package com.baeldung.transferqueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TransferQueue;
import java.util.concurrent.atomic.AtomicInteger;
public class Producer implements Runnable {
private static final Logger LOG = LoggerFactory.getLogger(Producer.class);
private final TransferQueue<String> transferQueue;
private final String name;
private final Integer numberOfMessagesToProduce;
public final AtomicInteger numberOfProducedMessages = new AtomicInteger();
public Producer(TransferQueue<String> transferQueue, String name, Integer numberOfMessagesToProduce) {
this.transferQueue = transferQueue;
this.name = name;
this.numberOfMessagesToProduce = numberOfMessagesToProduce;
}
@Override
public void run() {
for (int i = 0; i < numberOfMessagesToProduce; i++) {
try {
LOG.debug("Producer: " + name + " is waiting to transfer...");
boolean added = transferQueue.tryTransfer("A" + i, 4000, TimeUnit.MILLISECONDS);
if (added) {
numberOfProducedMessages.incrementAndGet();
LOG.debug("Producer: " + name + " transferred element: A" + i);
} else {
LOG.debug("can not add an element due to the timeout");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}