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:
committed by
Grzegorz Piwowarek
parent
09d10ac85f
commit
25263f1d6f
@@ -23,7 +23,6 @@
|
||||
- [Guide to Java Reflection](http://www.baeldung.com/java-reflection)
|
||||
- [A Guide to Java Sockets](http://www.baeldung.com/a-guide-to-java-sockets)
|
||||
- [Java 8 Collectors](http://www.baeldung.com/java-8-collectors)
|
||||
- [Guide To CompletableFuture](http://www.baeldung.com/java-completablefuture)
|
||||
- [Guide to Java 8’s Functional Interfaces](http://www.baeldung.com/java-8-functional-interfaces)
|
||||
- [Convert char to String in Java](http://www.baeldung.com/java-convert-char-to-string)
|
||||
- [Random List Element](http://www.baeldung.com/java-random-list-element)
|
||||
@@ -31,12 +30,10 @@
|
||||
- [Java 8 – Powerful Comparison with Lambdas](http://www.baeldung.com/java-8-sort-lambda)
|
||||
- [Java – Directory Size](http://www.baeldung.com/java-folder-size)
|
||||
- [Java – Try with Resources](http://www.baeldung.com/java-try-with-resources)
|
||||
- [A Guide to the Java ExecutorService](http://www.baeldung.com/java-executor-service-tutorial)
|
||||
- [Java 8 New Features](http://www.baeldung.com/java-8-new-features)
|
||||
- [Lambda Expressions and Functional Interfaces: Tips and Best Practices](http://www.baeldung.com/java-8-lambda-expressions-tips)
|
||||
- [The Double Colon Operator in Java 8](http://www.baeldung.com/java-8-double-colon-operator)
|
||||
- [Java 8 Streams Advanced](http://www.baeldung.com/java-8-streams)
|
||||
- [Introduction to Thread Pools in Java](http://www.baeldung.com/thread-pool-java-and-guava)
|
||||
- [Introduction to Java 8 Streams](http://www.baeldung.com/java-8-streams-introduction)
|
||||
- [Guide to the Fork/Join Framework in Java](http://www.baeldung.com/java-fork-join)
|
||||
- [How to Print Screen in Java](http://www.baeldung.com/print-screen-in-java)
|
||||
@@ -57,18 +54,11 @@
|
||||
- [The Basics of Java Generics](http://www.baeldung.com/java-generics)
|
||||
- [The Traveling Salesman Problem in Java](http://www.baeldung.com/java-simulated-annealing-for-traveling-salesman)
|
||||
- [How to Create an Executable JAR with Maven](http://www.baeldung.com/executable-jar-with-maven)
|
||||
- [Guide to java.util.concurrent.Future](http://www.baeldung.com/java-future)
|
||||
- [Guide to java.util.concurrent.BlockingQueue](http://www.baeldung.com/java-blocking-queue)
|
||||
- [Guide to CountDownLatch in Java](http://www.baeldung.com/java-countdown-latch)
|
||||
- [How to Design a Genetic Algorithm in Java](http://www.baeldung.com/java-genetic-algorithm)
|
||||
- [A Guide to ConcurrentMap](http://www.baeldung.com/java-concurrent-map)
|
||||
- [Guide to PriorityBlockingQueue in Java](http://www.baeldung.com/java-priority-blocking-queue)
|
||||
- [Guide to Java 8 groupingBy Collector](http://www.baeldung.com/java-groupingby-collector)
|
||||
- [Avoiding the ConcurrentModificationException in Java](http://www.baeldung.com/java-concurrentmodificationexception)
|
||||
- [Guide to WeakHashMap in Java](http://www.baeldung.com/java-weakhashmap)
|
||||
- [Strategy Design Pattern in Java 8](http://www.baeldung.com/java-strategy-pattern)
|
||||
- [Java 8 and Infinite Streams](http://www.baeldung.com/java-inifinite-streams)
|
||||
- [Custom Thread Pools In Java 8 Parallel Streams](http://www.baeldung.com/java-8-parallel-streams-custom-threadpool)
|
||||
- [String Operations with Java Streams](http://www.baeldung.com/java-stream-operations-on-strings)
|
||||
- [Spring Security – Cache Control Headers](http://www.baeldung.com/spring-security-cache-control-headers)
|
||||
- [Basic Introduction to JMX](http://www.baeldung.com/java-management-extensions)
|
||||
@@ -91,7 +81,6 @@
|
||||
- [Avoiding ConcurrentModificationException when iterating and removing](http://www.baeldung.com/avoiding-concurrentmodificationexception-when-iterating-and-removing)
|
||||
- [Removing all nulls from a List in Java](http://www.baeldung.com/java-remove-nulls-from-list)
|
||||
- [Removing all duplicates from a List in Java](http://www.baeldung.com/java-remove-duplicates-from-list)
|
||||
- [An Introduction to ThreadLocal in Java](http://www.baeldung.com/java-threadlocal)
|
||||
- [Using Math.pow in Java](http://www.baeldung.com/java-math-pow)
|
||||
- [Converting Strings to Enums in Java](http://www.baeldung.com/java-string-to-enum)
|
||||
- [Flattening Nested Collections in Java](http://www.baeldung.com/java-flatten-nested-collections)
|
||||
@@ -101,19 +90,12 @@
|
||||
- [HashSet and TreeSet Comparison](http://www.baeldung.com/java-hashset-vs-treeset)
|
||||
- [How to Perform a Simple HTTP Request in Java](http://www.baeldung.com/java-http-request)
|
||||
- [Call Methods at Runtime Using Java Reflection](http://www.baeldung.com/java-method-reflection)
|
||||
- [Guide to DelayQueue](http://www.baeldung.com/java-delay-queue)
|
||||
- [Guide to UUID in JAVA](http://www.baeldung.com/guide-to-uuid-in-java)
|
||||
- [Comparing getPath(), getAbsolutePath(), and getCanonicalPath() in Java](http://www.baeldung.com/java-path)
|
||||
- [How to Add a Single Element to a Stream](http://www.baeldung.com/java-stream-append-prepend)
|
||||
- [Iterating Over Enum Values in Java](http://www.baeldung.com/java-enum-iteration)
|
||||
- [A Guide to Java SynchronousQueue](http://www.baeldung.com/java-synchronous-queue)
|
||||
- [Guide to the Java TransferQueue](http://www.baeldung.com/java-transfer-queue)
|
||||
- [Kotlin Java Interoperability](http://www.baeldung.com/kotlin-java-interoperability)
|
||||
- [Guide to the ConcurrentSkipListMap](http://www.baeldung.com/java-concurrent-skip-list-map)
|
||||
- [Difference Between Wait and Sleep in Java](http://www.baeldung.com/java-wait-and-sleep)
|
||||
- [LongAdder and LongAccumulator in Java](http://www.baeldung.com/java-longadder-and-longaccumulator)
|
||||
- [Using Java MappedByteBuffer](http://www.baeldung.com/java-mapped-byte-buffer)
|
||||
- [The Dining Philosophers Problem in Java](http://www.baeldung.com/java-dining-philoshophers)
|
||||
- [The Difference Between map() and flatMap()](http://www.baeldung.com/java-difference-map-and-flatmap)
|
||||
- [How to Round a Number to N Decimal Places in Java](http://www.baeldung.com/java-round-decimal-number)
|
||||
- [Changing Annotation Parameters At Runtime](http://www.baeldung.com/java-reflection-change-annotation-params)
|
||||
@@ -122,21 +104,17 @@
|
||||
- [Changing the Order in a Sum Operation Can Produce Different Results?](http://www.baeldung.com/java-floating-point-sum-order)
|
||||
- [How to Get a Name of a Method Being Executed?](http://www.baeldung.com/java-name-of-executing-method)
|
||||
- [Iterate over a Map in Java](http://www.baeldung.com/java-iterate-map)
|
||||
- [CyclicBarrier in Java](http://www.baeldung.com/java-cyclic-barrier)
|
||||
- [Dynamic Proxies in Java](http://www.baeldung.com/java-dynamic-proxies)
|
||||
- [How to Copy an Array in Java](http://www.baeldung.com/java-array-copy)
|
||||
- [Introduction to JDBC](http://www.baeldung.com/java-jdbc)
|
||||
- [Guide to CopyOnWriteArrayList](http://www.baeldung.com/java-copy-on-write-arraylist)
|
||||
- [Period and Duration in Java](http://www.baeldung.com/java-period-duration)
|
||||
- [Converting a Stack Trace to a String in Java](http://www.baeldung.com/java-stacktrace-to-string)
|
||||
- [Guide to the Java Phaser](http://www.baeldung.com/java-phaser)
|
||||
- [Count Occurrences of a Char in a String](http://www.baeldung.com/java-count-chars)
|
||||
- [Java Double Brace Initialization](http://www.baeldung.com/java-double-brace-initialization)
|
||||
- [The StackOverflowError in Java](http://www.baeldung.com/java-stack-overflow-error)
|
||||
- [Split a String in Java](http://www.baeldung.com/java-split-string)
|
||||
- [Introduction to Java Serialization](http://www.baeldung.com/java-serialization)
|
||||
- [How to Remove the Last Character of a String?](http://www.baeldung.com/java-remove-last-character-of-string)
|
||||
- [Guide to Synchronized Keyword in Java](http://www.baeldung.com/java-synchronized)
|
||||
- [ClassNotFoundException vs NoClassDefFoundError](http://www.baeldung.com/java-classnotfoundexception-and-noclassdeffounderror)
|
||||
- [Guide to UUID in Java](http://www.baeldung.com/java-uuid)
|
||||
- [How to Get the Last Element of a Stream in Java?](http://www.baeldung.com/java-stream-last-element)
|
||||
|
||||
-34
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
-24
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-29
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
-27
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-120
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user