[BAEL-9555] - Created a core-java-modules folder
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
*.class
|
||||
|
||||
0.*
|
||||
|
||||
#folders#
|
||||
/target
|
||||
/neoDb*
|
||||
/data
|
||||
/src/main/webapp/WEB-INF/classes
|
||||
*/META-INF/*
|
||||
.resourceCache
|
||||
|
||||
# Packaged files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# Files generated by integration tests
|
||||
*.txt
|
||||
backup-pom.xml
|
||||
/bin/
|
||||
/temp
|
||||
|
||||
#IntelliJ specific
|
||||
.idea/
|
||||
*.iml
|
||||
@@ -0,0 +1,25 @@
|
||||
=========
|
||||
|
||||
## Core Java Concurrency Advanced Examples
|
||||
|
||||
### Relevant Articles:
|
||||
- [Introduction to Thread Pools in Java](http://www.baeldung.com/thread-pool-java-and-guava)
|
||||
- [Guide to CountDownLatch in Java](http://www.baeldung.com/java-countdown-latch)
|
||||
- [Guide to java.util.concurrent.Locks](http://www.baeldung.com/java-concurrent-locks)
|
||||
- [An Introduction to ThreadLocal in Java](http://www.baeldung.com/java-threadlocal)
|
||||
- [LongAdder and LongAccumulator in Java](http://www.baeldung.com/java-longadder-and-longaccumulator)
|
||||
- [The Dining Philosophers Problem in Java](http://www.baeldung.com/java-dining-philoshophers)
|
||||
- [Guide to the Java Phaser](http://www.baeldung.com/java-phaser)
|
||||
- [An Introduction to Atomic Variables in Java](http://www.baeldung.com/java-atomic-variables)
|
||||
- [CyclicBarrier in Java](http://www.baeldung.com/java-cyclic-barrier)
|
||||
- [Guide to the Volatile Keyword in Java](http://www.baeldung.com/java-volatile)
|
||||
- [Semaphores in Java](http://www.baeldung.com/java-semaphore)
|
||||
- [Daemon Threads in Java](http://www.baeldung.com/java-daemon-thread)
|
||||
- [Priority-based Job Scheduling in Java](http://www.baeldung.com/java-priority-job-schedule)
|
||||
- [Brief Introduction to Java Thread.yield()](https://www.baeldung.com/java-thread-yield)
|
||||
- [Print Even and Odd Numbers Using 2 Threads](https://www.baeldung.com/java-even-odd-numbers-with-2-threads)
|
||||
- [Java CyclicBarrier vs CountDownLatch](https://www.baeldung.com/java-cyclicbarrier-countdownlatch)
|
||||
- [Guide to the Fork/Join Framework in Java](http://www.baeldung.com/java-fork-join)
|
||||
- [Guide to ThreadLocalRandom in Java](http://www.baeldung.com/java-thread-local-random)
|
||||
- [The Thread.join() Method in Java](http://www.baeldung.com/java-thread-join)
|
||||
- [Passing Parameters to Java Threads](https://www.baeldung.com/java-thread-parameters)
|
||||
@@ -0,0 +1,86 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>core-java-concurrency-advanced</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<name>core-java-concurrency-advanced</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-java</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-java</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
<version>${commons-collections4.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons-io.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-math3</artifactId>
|
||||
<version>${commons-math3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>${assertj.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jayway.awaitility</groupId>
|
||||
<artifactId>awaitility</artifactId>
|
||||
<version>${avaitility.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-core</artifactId>
|
||||
<version>${jmh-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-generator-annprocess</artifactId>
|
||||
<version>${jmh-generator-annprocess.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>core-java-concurrency-advanced</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<!-- util -->
|
||||
<guava.version>21.0</guava.version>
|
||||
<commons-lang3.version>3.5</commons-lang3.version>
|
||||
<commons-math3.version>3.6.1</commons-math3.version>
|
||||
<commons-collections4.version>4.1</commons-collections4.version>
|
||||
<collections-generic.version>4.01</collections-generic.version>
|
||||
<!-- testing -->
|
||||
<assertj.version>3.6.1</assertj.version>
|
||||
<avaitility.version>1.7.0</avaitility.version>
|
||||
<jmh-core.version>1.19</jmh-core.version>
|
||||
<jmh-generator-annprocess.version>1.19</jmh-generator-annprocess.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.concurrent.atomic;
|
||||
|
||||
public class SafeCounterWithLock {
|
||||
private volatile int counter;
|
||||
|
||||
int getValue() {
|
||||
return counter;
|
||||
}
|
||||
|
||||
synchronized void increment() {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.concurrent.atomic;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class SafeCounterWithoutLock {
|
||||
private final AtomicInteger counter = new AtomicInteger(0);
|
||||
|
||||
int getValue() {
|
||||
return counter.get();
|
||||
}
|
||||
|
||||
void increment() {
|
||||
while(true) {
|
||||
int existingValue = getValue();
|
||||
int newValue = existingValue + 1;
|
||||
if(counter.compareAndSet(existingValue, newValue)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.concurrent.atomic;
|
||||
|
||||
public class UnsafeCounter {
|
||||
private int counter;
|
||||
|
||||
int getValue() {
|
||||
return counter;
|
||||
}
|
||||
|
||||
void increment() {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
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");
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package com.baeldung.concurrent.countdownlatch;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
public class CountdownLatchCountExample {
|
||||
|
||||
private int count;
|
||||
|
||||
public CountdownLatchCountExample(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public boolean callTwiceInSameThread() {
|
||||
CountDownLatch countDownLatch = new CountDownLatch(count);
|
||||
Thread t = new Thread(() -> {
|
||||
countDownLatch.countDown();
|
||||
countDownLatch.countDown();
|
||||
});
|
||||
t.start();
|
||||
|
||||
try {
|
||||
countDownLatch.await();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return countDownLatch.getCount() == 0;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
CountdownLatchCountExample ex = new CountdownLatchCountExample(2);
|
||||
System.out.println("Is CountDown Completed : " + ex.callTwiceInSameThread());
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.baeldung.concurrent.countdownlatch;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class CountdownLatchResetExample {
|
||||
|
||||
private int count;
|
||||
private int threadCount;
|
||||
private final AtomicInteger updateCount;
|
||||
|
||||
CountdownLatchResetExample(int count, int threadCount) {
|
||||
updateCount = new AtomicInteger(0);
|
||||
this.count = count;
|
||||
this.threadCount = threadCount;
|
||||
}
|
||||
|
||||
public int countWaits() {
|
||||
CountDownLatch countDownLatch = new CountDownLatch(count);
|
||||
ExecutorService es = Executors.newFixedThreadPool(threadCount);
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
es.execute(() -> {
|
||||
long prevValue = countDownLatch.getCount();
|
||||
countDownLatch.countDown();
|
||||
if (countDownLatch.getCount() != prevValue) {
|
||||
updateCount.incrementAndGet();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
es.shutdown();
|
||||
return updateCount.get();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
CountdownLatchResetExample ex = new CountdownLatchResetExample(5, 20);
|
||||
System.out.println("Count : " + ex.countWaits());
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package com.baeldung.concurrent.cyclicbarrier;
|
||||
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class CyclicBarrierCompletionMethodExample {
|
||||
|
||||
private int count;
|
||||
private int threadCount;
|
||||
private final AtomicInteger updateCount;
|
||||
|
||||
CyclicBarrierCompletionMethodExample(int count, int threadCount) {
|
||||
updateCount = new AtomicInteger(0);
|
||||
this.count = count;
|
||||
this.threadCount = threadCount;
|
||||
}
|
||||
|
||||
public int countTrips() {
|
||||
|
||||
CyclicBarrier cyclicBarrier = new CyclicBarrier(count, () -> {
|
||||
updateCount.incrementAndGet();
|
||||
});
|
||||
|
||||
ExecutorService es = Executors.newFixedThreadPool(threadCount);
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
es.execute(() -> {
|
||||
try {
|
||||
cyclicBarrier.await();
|
||||
} catch (InterruptedException | BrokenBarrierException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
es.shutdown();
|
||||
return updateCount.get();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
CyclicBarrierCompletionMethodExample ex = new CyclicBarrierCompletionMethodExample(5, 20);
|
||||
System.out.println("Count : " + ex.countTrips());
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.baeldung.concurrent.cyclicbarrier;
|
||||
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
|
||||
public class CyclicBarrierCountExample {
|
||||
|
||||
private int count;
|
||||
|
||||
public CyclicBarrierCountExample(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public boolean callTwiceInSameThread() {
|
||||
CyclicBarrier cyclicBarrier = new CyclicBarrier(count);
|
||||
Thread t = new Thread(() -> {
|
||||
try {
|
||||
cyclicBarrier.await();
|
||||
cyclicBarrier.await();
|
||||
} catch (InterruptedException | BrokenBarrierException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
return cyclicBarrier.isBroken();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
CyclicBarrierCountExample ex = new CyclicBarrierCountExample(7);
|
||||
System.out.println("Count : " + ex.callTwiceInSameThread());
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package com.baeldung.concurrent.cyclicbarrier;
|
||||
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class CyclicBarrierResetExample {
|
||||
|
||||
private int count;
|
||||
private int threadCount;
|
||||
private final AtomicInteger updateCount;
|
||||
|
||||
CyclicBarrierResetExample(int count, int threadCount) {
|
||||
updateCount = new AtomicInteger(0);
|
||||
this.count = count;
|
||||
this.threadCount = threadCount;
|
||||
}
|
||||
|
||||
public int countWaits() {
|
||||
|
||||
CyclicBarrier cyclicBarrier = new CyclicBarrier(count);
|
||||
|
||||
ExecutorService es = Executors.newFixedThreadPool(threadCount);
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
es.execute(() -> {
|
||||
try {
|
||||
if (cyclicBarrier.getNumberWaiting() > 0) {
|
||||
updateCount.incrementAndGet();
|
||||
}
|
||||
cyclicBarrier.await();
|
||||
} catch (InterruptedException | BrokenBarrierException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
es.shutdown();
|
||||
return updateCount.get();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
CyclicBarrierResetExample ex = new CyclicBarrierResetExample(7, 20);
|
||||
System.out.println("Count : " + ex.countWaits());
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.baeldung.concurrent.daemon;
|
||||
|
||||
public class MultipleThreadsExample {
|
||||
public static void main(String[] args) {
|
||||
NewThread t1 = new NewThread();
|
||||
t1.setName("MyThread-1");
|
||||
NewThread t2 = new NewThread();
|
||||
t2.setName("MyThread-2");
|
||||
t1.start();
|
||||
t2.start();
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.concurrent.daemon;
|
||||
|
||||
public class NewThread extends Thread {
|
||||
public void run() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
while (true) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
System.out.println(this.getName() + ": New Thread is running..." + i);
|
||||
try {
|
||||
//Wait for one sec so it doesn't print too fast
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// prevent the Thread to run forever. It will finish it's execution after 2 seconds
|
||||
if (System.currentTimeMillis() - startTime > 2000) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package com.baeldung.concurrent.daemon;
|
||||
|
||||
public class SingleThreadExample {
|
||||
public static void main(String[] args) {
|
||||
NewThread t = new NewThread();
|
||||
t.start();
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
package com.baeldung.concurrent.evenandodd;
|
||||
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
public class PrintEvenOddSemaphore {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SharedPrinter sp = new SharedPrinter();
|
||||
Thread odd = new Thread(new Odd(sp, 10), "Odd");
|
||||
Thread even = new Thread(new Even(sp, 10), "Even");
|
||||
|
||||
odd.start();
|
||||
even.start();
|
||||
}
|
||||
}
|
||||
|
||||
class SharedPrinter {
|
||||
|
||||
private final Semaphore semEven = new Semaphore(0);
|
||||
private final Semaphore semOdd = new Semaphore(1);
|
||||
|
||||
void printEvenNum(int num) {
|
||||
try {
|
||||
semEven.acquire();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
System.out.println(Thread.currentThread().getName() + ":"+num);
|
||||
semOdd.release();
|
||||
}
|
||||
|
||||
void printOddNum(int num) {
|
||||
try {
|
||||
semOdd.acquire();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
System.out.println(Thread.currentThread().getName() + ":"+ num);
|
||||
semEven.release();
|
||||
}
|
||||
}
|
||||
|
||||
class Even implements Runnable {
|
||||
private final SharedPrinter sp;
|
||||
private final int max;
|
||||
|
||||
Even(SharedPrinter sp, int max) {
|
||||
this.sp = sp;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (int i = 2; i <= max; i = i + 2) {
|
||||
sp.printEvenNum(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Odd implements Runnable {
|
||||
private SharedPrinter sp;
|
||||
private int max;
|
||||
|
||||
Odd(SharedPrinter sp, int max) {
|
||||
this.sp = sp;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (int i = 1; i <= max; i = i + 2) {
|
||||
sp.printOddNum(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package com.baeldung.concurrent.evenandodd;
|
||||
|
||||
public class PrintEvenOddWaitNotify {
|
||||
|
||||
public static void main(String... args) {
|
||||
Printer print = new Printer();
|
||||
Thread t1 = new Thread(new TaskEvenOdd(print, 10, false), "Odd");
|
||||
Thread t2 = new Thread(new TaskEvenOdd(print, 10, true), "Even");
|
||||
t1.start();
|
||||
t2.start();
|
||||
}
|
||||
}
|
||||
|
||||
class TaskEvenOdd implements Runnable {
|
||||
private final int max;
|
||||
private final Printer print;
|
||||
private final boolean isEvenNumber;
|
||||
|
||||
TaskEvenOdd(Printer print, int max, boolean isEvenNumber) {
|
||||
this.print = print;
|
||||
this.max = max;
|
||||
this.isEvenNumber = isEvenNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
int number = isEvenNumber ? 2 : 1;
|
||||
while (number <= max) {
|
||||
if (isEvenNumber) {
|
||||
print.printEven(number);
|
||||
} else {
|
||||
print.printOdd(number);
|
||||
}
|
||||
number += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Printer {
|
||||
private volatile boolean isOdd;
|
||||
|
||||
synchronized void printEven(int number) {
|
||||
while (!isOdd) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
System.out.println(Thread.currentThread().getName() + ":" + number);
|
||||
isOdd = false;
|
||||
notify();
|
||||
}
|
||||
|
||||
synchronized void printOdd(int number) {
|
||||
while (isOdd) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
System.out.println(Thread.currentThread().getName() + ":" + number);
|
||||
isOdd = true;
|
||||
notify();
|
||||
}
|
||||
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
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
@@ -0,0 +1,120 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.baeldung.concurrent.parameter;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class AverageCalculator implements Callable<Double> {
|
||||
|
||||
int[] numbers;
|
||||
|
||||
public AverageCalculator(int... parameter) {
|
||||
this.numbers = parameter == null ? new int[0] : parameter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double call() throws Exception {
|
||||
return IntStream.of(this.numbers)
|
||||
.average()
|
||||
.orElse(0d);
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.baeldung.concurrent.parameter;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class ParameterizedThreadExample {
|
||||
|
||||
public static void parameterisedThreadAnonymousClass() {
|
||||
final String parameter = "123";
|
||||
Thread parameterizedThread = new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println(Thread.currentThread()
|
||||
.getName() + " : " + parameter);
|
||||
}
|
||||
});
|
||||
|
||||
parameterizedThread.start();
|
||||
}
|
||||
|
||||
public static Callable<Integer> sumCalculator(int... numbers) {
|
||||
return () -> numbers != null ? IntStream.of(numbers)
|
||||
.sum() : 0;
|
||||
}
|
||||
|
||||
public static Callable<Double> averageCalculator(int... numbers) {
|
||||
return () -> numbers != null ? IntStream.of(numbers)
|
||||
.average()
|
||||
.orElse(0d) : 0d;
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package com.baeldung.concurrent.prioritytaskexecution;
|
||||
|
||||
public class Job implements Runnable {
|
||||
private String jobName;
|
||||
private JobPriority jobPriority;
|
||||
|
||||
public Job(String jobName, JobPriority jobPriority) {
|
||||
this.jobName = jobName;
|
||||
this.jobPriority = jobPriority != null ? jobPriority : JobPriority.MEDIUM;
|
||||
}
|
||||
|
||||
public JobPriority getJobPriority() {
|
||||
return jobPriority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
System.out.println("Job:" + jobName +
|
||||
" Priority:" + jobPriority);
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user