├── .gitignore
├── AQS
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ └── AQSUsage.java
├── CAS
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ └── CasCounter.java
├── CompletableFuture
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ └── CompletableFutureUsage.java
├── CompletionService
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ └── CompletionServiceUsage.java
├── CountDownLatch
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── com.flydean
│ │ ├── MainThreadWaitUsage.java
│ │ └── ThreadWaitThreadUsage.java
│ └── test
│ └── java
│ ├── MainThreadWaitUsageTest.java
│ └── ThreadWaitThreadUsageTest.java
├── CyclicBarrier
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── com
│ │ └── flydean
│ │ └── CyclicBarrierUsage.java
│ └── test
│ └── java
│ └── CyclicBarrierUsageTest.java
├── DaemonThread
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ ├── DaemonBThread.java
│ └── DaemonThread.java
├── Exchanger
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com.flydean
│ ├── CustBook.java
│ ├── ExchangerOne.java
│ ├── ExchangerTwo.java
│ └── ExchangerUsage.java
├── ExecutorService
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ └── ExecutorServiceUsage.java
├── ExecutorServiceShutdown
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ ├── ShutdownNowUsage.java
│ ├── ShutdownUsage.java
│ └── TrackingExecutor.java
├── Locks
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com.flydean
│ ├── ConditionUsage.java
│ ├── ReentrantLockUsage.java
│ ├── ReentrantReadWriteLockUsage.java
│ └── StampedLockUsage.java
├── MemoizedCalculate
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com.flydean
│ ├── Calculator.java
│ ├── MemoizedCalculator1.java
│ ├── MemoizedCalculator2.java
│ ├── MemoizedCalculator3.java
│ └── MemoizedCalculator4.java
├── Phaser
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com.flydean
│ ├── PhaserTask.java
│ └── PhaserUsage.java
├── RCU
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ └── RCU.java
├── README.md
├── Semaphore
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com.flydean
│ └── SemaphoreUsage.java
├── Synchronized
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── com
│ │ └── flydean
│ │ └── SynchronizedMethods.java
│ └── test
│ └── java
│ └── com
│ └── flydean
│ └── SynchronizedMethodsTest.java
├── ThreadLocal
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── com
│ │ └── flydean
│ │ ├── Context.java
│ │ ├── SharedMapWithUserContext.java
│ │ ├── ThreadLocalUsage.java
│ │ ├── ThreadLocalWithUserContext.java
│ │ └── UserRepository.java
│ └── test
│ └── java
│ └── com
│ └── flydean
│ ├── ShareMapWithUserContextTest.java
│ └── ThreadLocalWithUserContextTest.java
├── ThreadLocalRandom
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com.flydean
│ ├── RandomUsage.java
│ └── ThreadLocalRandomUsage.java
├── ThreadPoolDeadlock
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ └── ThreadPoolDeadlock.java
├── accountTransferLock
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ ├── Account.java
│ ├── AccountTransfer.java
│ └── InsufficientAmountException.java
├── atomic
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ ├── AtomicCounter.java
│ ├── Counter.java
│ └── LockCounter.java
├── benchmark
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com.flydean
│ ├── BenchMarkUsage.java
│ └── StateUsage.java
├── concurrent-overview
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ ├── CyclicBarrierUsage.java
│ ├── ExecutorServiceUsage.java
│ ├── FutureUsage.java
│ ├── Invoker.java
│ ├── ScheduledExecutorServiceUsage.java
│ ├── SemaphoreUsage.java
│ ├── Task.java
│ └── ThreadFactoryUsage.java
├── forkjoin
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com.flydean
│ ├── CustomRecursiveAction.java
│ ├── CustomRecursiveTask.java
│ └── ForkJoinUsage.java
├── future
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ └── FutureUsage.java
├── futureTask
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com.flydean
│ └── FutureTaskUsage.java
├── interrupt
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ └── InterruptThread.java
├── join
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ └── JoinThread.java
├── kill-thread
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ └── KillThread.java
├── nonblock
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com.flydean
│ ├── ConcurrentStack.java
│ ├── LinkedNode.java
│ ├── LinkedQueue.java
│ └── Node.java
├── pom.xml
├── rejectPolicy
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ ├── RejectPolicyUsage.java
│ └── SemaphoreUsage.java
├── reorder
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com.flydean
│ ├── Book.java
│ ├── BookDLC.java
│ ├── BookStatic.java
│ ├── BookStaticLazy.java
│ ├── FinalSafe.java
│ └── Reorder.java
├── runnable-callable
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ ├── CallableUsage.java
│ ├── CustomerException.java
│ └── RunnableUsage.java
├── thread-lifecycle
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ ├── BlockThread.java
│ ├── NewThread.java
│ ├── RunnableThread.java
│ ├── TerminatedThread.java
│ ├── TimedWaitThread.java
│ └── WaitThread.java
├── threadPool
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── flydean
│ ├── CountingTask.java
│ ├── ExecutorServiceUsage.java
│ ├── ScheduledThreadPoolExecutorUsage.java
│ ├── ThreadPoolExecutorUsage.java
│ └── TreeNode.java
├── volatile
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── com
│ │ └── flydean
│ │ ├── VolatileFalseUsage.java
│ │ ├── VolatileHappenBeforeUsage.java
│ │ ├── VolatileTrueUsage.java
│ │ └── VolatileWithoutUsage.java
│ └── test
│ └── java
│ └── com
│ └── flydean
│ └── VolatileUsageTest.java
└── wait-sleep
├── pom.xml
└── src
├── main
└── java
│ └── com
│ └── flydean
│ ├── SleepUsage.java
│ ├── WaitNotifyUsage.java
│ └── WaitUsage.java
└── test
└── java
└── WaitUsageTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
33 | .DS_Store
34 |
--------------------------------------------------------------------------------
/AQS/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | AQS
13 |
14 |
15 |
--------------------------------------------------------------------------------
/AQS/src/main/java/com/flydean/AQSUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.concurrent.locks.AbstractQueuedSynchronizer;
4 |
5 | /**
6 | * @author wayne
7 | * @version AQSUsage, 2020/3/26 11:27 下午
8 | */
9 | public class AQSUsage {
10 |
11 | private final Sync sync= new Sync();
12 |
13 | private class Sync extends AbstractQueuedSynchronizer{
14 | protected int tryAcquireShared(int ignored){
15 | return (getState() ==1 )? 1: -1;
16 | }
17 | protected boolean tryReleaseShared(int ignored){
18 | setState(1);
19 | return true;
20 | }
21 | }
22 |
23 | public void release() {
24 | sync.releaseShared(0);
25 | }
26 | public void acquire() throws InterruptedException {
27 | sync.acquireSharedInterruptibly(0);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/CAS/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | CAS
13 |
14 |
15 |
--------------------------------------------------------------------------------
/CAS/src/main/java/com/flydean/CasCounter.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import sun.misc.Unsafe;
4 |
5 | /**
6 | * @author wayne
7 | * @version CasCounter, 2020/3/27 7:38 上午
8 | */
9 | public class CasCounter {
10 |
11 | private static final Unsafe unsafe = Unsafe.getUnsafe();
12 | private static final long valueOffset;
13 | private volatile int value;
14 |
15 | static {
16 | try {
17 | valueOffset = unsafe.objectFieldOffset
18 | (CasCounter.class.getDeclaredField("value"));
19 | } catch (Exception ex) { throw new Error(ex); }
20 | }
21 |
22 | public CasCounter(int initialValue) {
23 | value = initialValue;
24 | }
25 |
26 | public CasCounter() {
27 | }
28 |
29 | public final int get() {
30 | return value;
31 | }
32 |
33 | public final void set(int newValue) {
34 | value = newValue;
35 | }
36 |
37 | public final boolean compareAndSet(int expect, int update) {
38 | return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/CompletableFuture/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | CompletableFuture
13 |
14 |
15 |
--------------------------------------------------------------------------------
/CompletableFuture/src/main/java/com/flydean/CompletableFutureUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.util.concurrent.CompletableFuture;
6 | import java.util.concurrent.Executors;
7 | import java.util.concurrent.Future;
8 | import java.util.stream.Collectors;
9 | import java.util.stream.Stream;
10 |
11 | /**
12 | * @author wayne
13 | * @version CompletableFutureUsage, 2020/3/15 11:15 下午
14 | */
15 | @Slf4j
16 | public class CompletableFutureUsage {
17 |
18 | public Future calculateAsync() throws InterruptedException {
19 | CompletableFuture completableFuture
20 | = new CompletableFuture<>();
21 |
22 | Executors.newCachedThreadPool().submit(() -> {
23 | Thread.sleep(500);
24 | completableFuture.complete("Hello");
25 | return null;
26 | });
27 |
28 | return completableFuture;
29 | }
30 |
31 | public Future useCompletableFuture(){
32 | Future completableFuture =
33 | CompletableFuture.completedFuture("Hello");
34 | return completableFuture;
35 | }
36 |
37 | public Future calculateAsyncWithCancellation() throws InterruptedException {
38 | CompletableFuture completableFuture = new CompletableFuture<>();
39 |
40 | Executors.newCachedThreadPool().submit(() -> {
41 | Thread.sleep(500);
42 | completableFuture.cancel(false);
43 | return null;
44 | });
45 | return completableFuture;
46 | }
47 |
48 | public void runAsync(){
49 | CompletableFuture runAsync= CompletableFuture.runAsync(()->{
50 | log.info("runAsync");
51 | });
52 | }
53 |
54 | public void supplyAsync(){
55 | CompletableFuture supplyAsync=CompletableFuture.supplyAsync(()->{
56 | return "supplyAsync";
57 | });
58 | }
59 |
60 | public void thenCompose(){
61 | CompletableFuture completableFuture
62 | = CompletableFuture.supplyAsync(() -> "Hello")
63 | .thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World"));
64 | }
65 |
66 | public void thenApply(){
67 | CompletableFuture finalResult
68 | = CompletableFuture.supplyAsync(() -> "Hello").thenApply(s-> s + 1);
69 | }
70 |
71 | public void thenCombine(){
72 | CompletableFuture completableFuture
73 | = CompletableFuture.supplyAsync(() -> "Hello")
74 | .thenCombine(CompletableFuture.supplyAsync(
75 | () -> " World"), (s1, s2) -> s1 + s2);
76 | }
77 |
78 | public void thenAcceptBoth(){
79 | CompletableFuture future = CompletableFuture.supplyAsync(() -> "Hello")
80 | .thenAcceptBoth(CompletableFuture.supplyAsync(() -> " World"),
81 | (s1, s2) -> System.out.println(s1 + s2));
82 | }
83 |
84 | public void allOf(){
85 | CompletableFuture future1
86 | = CompletableFuture.supplyAsync(() -> "Hello");
87 | CompletableFuture future2
88 | = CompletableFuture.supplyAsync(() -> "Beautiful");
89 | CompletableFuture future3
90 | = CompletableFuture.supplyAsync(() -> "World");
91 |
92 | CompletableFuture combinedFuture
93 | = CompletableFuture.allOf(future1, future2, future3);
94 | }
95 |
96 | public void join(){
97 | CompletableFuture future1
98 | = CompletableFuture.supplyAsync(() -> "Hello");
99 | CompletableFuture future2
100 | = CompletableFuture.supplyAsync(() -> "Beautiful");
101 | CompletableFuture future3
102 | = CompletableFuture.supplyAsync(() -> "World");
103 |
104 | String combined = Stream.of(future1, future2, future3)
105 | .map(CompletableFuture::join)
106 | .collect(Collectors.joining(" "));
107 | }
108 |
109 | public void handleError(){
110 | String name = null;
111 |
112 | CompletableFuture completableFuture
113 | = CompletableFuture.supplyAsync(() -> {
114 | if (name == null) {
115 | throw new RuntimeException("Computation error!");
116 | }
117 | return "Hello, " + name;
118 | }).handle((s, t) -> s != null ? s : "Hello, Stranger!");
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/CompletionService/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | CompletionService
13 |
14 |
15 |
--------------------------------------------------------------------------------
/CompletionService/src/main/java/com/flydean/CompletionServiceUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.concurrent.*;
6 |
7 | /**
8 | * @author wayne
9 | * @version CompletionServiceUsage, 2020/3/22 10:22 下午
10 | */
11 | public class CompletionServiceUsage {
12 |
13 | public void useExecutorService() throws InterruptedException {
14 | ExecutorService executor = Executors.newFixedThreadPool(10);
15 |
16 | Callable callableTask = () -> {
17 | TimeUnit.MILLISECONDS.sleep(300);
18 | return "Task's execution";
19 | };
20 |
21 | List> callableTasks = new ArrayList<>();
22 | callableTasks.add(callableTask);
23 | callableTasks.add(callableTask);
24 | callableTasks.add(callableTask);
25 |
26 | List> futures = executor.invokeAll(callableTasks);
27 |
28 | executor.shutdown();
29 |
30 | }
31 |
32 | public void useCompletionService() throws InterruptedException, ExecutionException {
33 | ExecutorService executor = Executors.newFixedThreadPool(10);
34 | CompletionService completionService=new ExecutorCompletionService(executor);
35 | Callable callableTask = () -> {
36 | TimeUnit.MILLISECONDS.sleep(300);
37 | return "Task's execution";
38 | };
39 | for(int i=0; i< 5; i ++){
40 | completionService.submit(callableTask);
41 | }
42 |
43 | for(int i=0; i<5; i++){
44 | Future result=completionService.take();
45 | System.out.println(result.get());
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/CountDownLatch/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | CountDownLatch
13 |
14 |
15 | junit
16 | junit
17 | 4.13.1
18 | compile
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/CountDownLatch/src/main/java/com.flydean/MainThreadWaitUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.util.List;
6 | import java.util.concurrent.CountDownLatch;
7 |
8 | /**
9 | * @author wayne
10 | * @version CountDownLatchUsage, 2020/3/10 11:47 下午
11 | */
12 | @Slf4j
13 | public class MainThreadWaitUsage implements Runnable {
14 |
15 | private List outputScraper;
16 | private CountDownLatch countDownLatch;
17 |
18 | public MainThreadWaitUsage(List outputScraper, CountDownLatch countDownLatch) {
19 | this.outputScraper = outputScraper;
20 | this.countDownLatch = countDownLatch;
21 | }
22 |
23 | @Override
24 | public void run() {
25 | outputScraper.add("Counted down");
26 | countDownLatch.countDown();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/CountDownLatch/src/main/java/com.flydean/ThreadWaitThreadUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.List;
4 | import java.util.concurrent.CountDownLatch;
5 |
6 | /**
7 | * @author wayne
8 | * @version ThreadWaitThreadUsage, 2020/3/11 12:06 上午
9 | */
10 | public class ThreadWaitThreadUsage implements Runnable {
11 |
12 | private List outputScraper;
13 | private CountDownLatch readyThreadCounter;
14 | private CountDownLatch callingThreadBlocker;
15 | private CountDownLatch completedThreadCounter;
16 |
17 | public ThreadWaitThreadUsage(
18 | List outputScraper,
19 | CountDownLatch readyThreadCounter,
20 | CountDownLatch callingThreadBlocker,
21 | CountDownLatch completedThreadCounter) {
22 |
23 | this.outputScraper = outputScraper;
24 | this.readyThreadCounter = readyThreadCounter;
25 | this.callingThreadBlocker = callingThreadBlocker;
26 | this.completedThreadCounter = completedThreadCounter;
27 | }
28 |
29 | @Override
30 | public void run() {
31 | readyThreadCounter.countDown();
32 | try {
33 | callingThreadBlocker.await();
34 | outputScraper.add("Counted down");
35 | } catch (InterruptedException e) {
36 | e.printStackTrace();
37 | } finally {
38 | completedThreadCounter.countDown();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/CountDownLatch/src/test/java/MainThreadWaitUsageTest.java:
--------------------------------------------------------------------------------
1 | import com.flydean.MainThreadWaitUsage;
2 | import lombok.extern.slf4j.Slf4j;
3 | import org.junit.Test;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Collections;
7 | import java.util.List;
8 | import java.util.concurrent.CountDownLatch;
9 | import java.util.stream.Stream;
10 |
11 | import static java.util.stream.Collectors.toList;
12 |
13 | /**
14 | * @author wayne
15 | * @version CountDownLatchTest, 2020/3/10 11:55 下午
16 | */
17 |
18 | @Slf4j
19 | public class MainThreadWaitUsageTest {
20 |
21 |
22 | @Test
23 | public void testCountDownLatch()
24 | throws InterruptedException {
25 |
26 | List outputScraper = Collections.synchronizedList(new ArrayList<>());
27 | CountDownLatch countDownLatch = new CountDownLatch(5);
28 | List workers = Stream
29 | .generate(() -> new Thread(new MainThreadWaitUsage(outputScraper, countDownLatch)))
30 | .limit(5)
31 | .collect(toList());
32 |
33 | workers.forEach(Thread::start);
34 | countDownLatch.await();
35 | outputScraper.add("Latch released");
36 | log.info(outputScraper.toString());
37 |
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/CountDownLatch/src/test/java/ThreadWaitThreadUsageTest.java:
--------------------------------------------------------------------------------
1 | import com.flydean.ThreadWaitThreadUsage;
2 | import lombok.extern.slf4j.Slf4j;
3 | import org.junit.Test;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Collections;
7 | import java.util.List;
8 | import java.util.concurrent.CountDownLatch;
9 | import java.util.stream.Stream;
10 |
11 | import static java.util.stream.Collectors.toList;
12 |
13 | /**
14 | * @author wayne
15 | * @version ThreadWaitThreadUsageTest, 2020/3/11 12:07 上午
16 | */
17 | @Slf4j
18 | public class ThreadWaitThreadUsageTest {
19 |
20 | @Test
21 | public void testCountDownLatch()
22 | throws InterruptedException {
23 |
24 | List outputScraper = Collections.synchronizedList(new ArrayList<>());
25 | CountDownLatch readyThreadCounter = new CountDownLatch(5);
26 | CountDownLatch callingThreadBlocker = new CountDownLatch(1);
27 | CountDownLatch completedThreadCounter = new CountDownLatch(5);
28 | List workers = Stream
29 | .generate(() -> new Thread(new ThreadWaitThreadUsage(
30 | outputScraper, readyThreadCounter, callingThreadBlocker, completedThreadCounter)))
31 | .limit(5)
32 | .collect(toList());
33 |
34 | workers.forEach(Thread::start);
35 | readyThreadCounter.await();
36 | outputScraper.add("Workers ready");
37 | callingThreadBlocker.countDown();
38 | completedThreadCounter.await();
39 | outputScraper.add("Workers complete");
40 |
41 | log.info(outputScraper.toString());
42 |
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/CyclicBarrier/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | CyclicBarrier
13 |
14 |
15 | junit
16 | junit
17 | 4.13.1
18 | test
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/CyclicBarrier/src/main/java/com/flydean/CyclicBarrierUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.Random;
6 | import java.util.concurrent.BrokenBarrierException;
7 | import java.util.concurrent.CyclicBarrier;
8 |
9 | /**
10 | * @author wayne
11 | * @version CyclicBarrierUsage, 2020/3/11 10:27 上午
12 | */
13 | public class CyclicBarrierUsage implements Runnable {
14 |
15 | private CyclicBarrier cyclicBarrier;
16 | private List> partialResults;
17 | private Random random = new Random();
18 |
19 | public CyclicBarrierUsage(CyclicBarrier cyclicBarrier,List> partialResults){
20 | this.cyclicBarrier=cyclicBarrier;
21 | this.partialResults=partialResults;
22 | }
23 |
24 | @Override
25 | public void run() {
26 | String thisThreadName = Thread.currentThread().getName();
27 | List partialResult = new ArrayList<>();
28 |
29 | // Crunch some numbers and store the partial result
30 | for (int i = 0; i < 10; i++) {
31 | Integer num = random.nextInt(10);
32 | System.out.println(thisThreadName
33 | + ": Crunching some numbers! Final result - " + num);
34 | partialResult.add(num);
35 | }
36 |
37 | partialResults.add(partialResult);
38 | try {
39 | System.out.println(thisThreadName
40 | + " waiting for others to reach barrier.");
41 | cyclicBarrier.await();
42 | } catch (InterruptedException e) {
43 | // ...
44 | } catch (BrokenBarrierException e) {
45 | // ...
46 | }
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/CyclicBarrier/src/test/java/CyclicBarrierUsageTest.java:
--------------------------------------------------------------------------------
1 | import com.flydean.CyclicBarrierUsage;
2 | import org.junit.Test;
3 |
4 | import java.util.ArrayList;
5 | import java.util.Collections;
6 | import java.util.List;
7 | import java.util.concurrent.CyclicBarrier;
8 |
9 | /**
10 | * @author wayne
11 | * @version CyclicBarrierUsageTest, 2020/3/11 10:36 上午
12 | */
13 | public class CyclicBarrierUsageTest {
14 |
15 | @Test
16 | public void testCyclicBarrier(){
17 | List> partialResults
18 | = Collections.synchronizedList(new ArrayList<>());
19 | CyclicBarrier cyclicBarrier=new CyclicBarrier(5,()->{
20 | String thisThreadName = Thread.currentThread().getName();
21 |
22 | System.out.println(
23 | thisThreadName + ": Computing sum of 5 workers, having 10 results each.");
24 | int sum = 0;
25 |
26 | for (List threadResult : partialResults) {
27 | System.out.print("Adding ");
28 | for (Integer partialResult : threadResult) {
29 | System.out.print(partialResult+" ");
30 | sum += partialResult;
31 | }
32 | System.out.println();
33 | }
34 | System.out.println(thisThreadName + ": Final result = " + sum);
35 | });
36 |
37 | System.out.println("Spawning 5 worker threads to compute 10 partial results each");
38 |
39 | for (int i = 0; i < 5; i++) {
40 | Thread worker = new Thread(new CyclicBarrierUsage(cyclicBarrier,partialResults));
41 | worker.setName("Thread " + i);
42 | worker.start();
43 | }
44 | }
45 |
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/DaemonThread/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | DaemonThread
13 |
14 |
15 | junit
16 | junit
17 | 4.13.1
18 | compile
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/DaemonThread/src/main/java/com/flydean/DaemonBThread.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | /**
6 | * @author wayne
7 | * @version DaemonThread, 2020/3/5 9:33 上午
8 | */
9 | @Slf4j
10 | public class DaemonBThread extends Thread{
11 |
12 | Thread worker = new Thread(()->{
13 | while(true){
14 | log.info("Thread B run");
15 | log.info("Thread B is daemon {}",Thread.currentThread().isDaemon());
16 | }
17 | });
18 | public void run(){
19 | log.info("Thread A run");
20 | worker.start();
21 | }
22 |
23 | public static void main(String[] args) {
24 | DaemonBThread daemonThread = new DaemonBThread();
25 | daemonThread.setDaemon(true);
26 | daemonThread.start();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/DaemonThread/src/main/java/com/flydean/DaemonThread.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.junit.Test;
5 |
6 | /**
7 | * @author wayne
8 | * @version DaemonThread, 2020/3/5 9:33 上午
9 | */
10 | @Slf4j
11 | public class DaemonThread extends Thread{
12 |
13 | public void run(){
14 | while(true){
15 | log.info("Thread A run");
16 | try {
17 | log.info("Thread A is daemon {}" ,Thread.currentThread().isDaemon());
18 | Thread.sleep(1000);
19 | } catch (InterruptedException e) {
20 | e.printStackTrace();
21 | }
22 | }
23 | }
24 |
25 | @Test
26 | public void testDaemon() throws InterruptedException {
27 | DaemonThread daemonThread = new DaemonThread();
28 | daemonThread.start();
29 | Thread.sleep(2000);
30 | }
31 |
32 |
33 | public static void main(String[] args) throws InterruptedException {
34 | DaemonThread daemonThread = new DaemonThread();
35 | daemonThread.setDaemon(true);
36 | daemonThread.start();
37 | Thread.sleep(2000);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Exchanger/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | Exchanger
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Exchanger/src/main/java/com.flydean/CustBook.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @author wayne
7 | * @version CustBook, 2020/4/10 10:05 下午
8 | */
9 | @Data
10 | public class CustBook {
11 |
12 | private String name;
13 | }
14 |
--------------------------------------------------------------------------------
/Exchanger/src/main/java/com.flydean/ExchangerOne.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.util.concurrent.Exchanger;
6 |
7 | /**
8 | * @author wayne
9 | * @version ExchangerOne, 2020/4/10 10:08 下午
10 | */
11 | @Slf4j
12 | public class ExchangerOne implements Runnable{
13 |
14 | Exchanger ex;
15 |
16 | ExchangerOne(Exchanger ex){
17 | this.ex=ex;
18 | }
19 |
20 | @Override
21 | public void run() {
22 | CustBook custBook= new CustBook();
23 | custBook.setName("book one");
24 |
25 | try {
26 | CustBook exhangeCustBook=ex.exchange(custBook);
27 | log.info(exhangeCustBook.getName());
28 | } catch (InterruptedException e) {
29 | e.printStackTrace();
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Exchanger/src/main/java/com.flydean/ExchangerTwo.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.util.concurrent.Exchanger;
6 |
7 | /**
8 | * @author wayne
9 | * @version ExchangerTwo, 2020/4/10 10:08 下午
10 | */
11 | @Slf4j
12 | public class ExchangerTwo implements Runnable{
13 |
14 | Exchanger ex;
15 |
16 | ExchangerTwo(Exchanger ex){
17 | this.ex=ex;
18 | }
19 |
20 | @Override
21 | public void run() {
22 | CustBook custBook= new CustBook();
23 | custBook.setName("book two");
24 |
25 | try {
26 | CustBook exhangeCustBook=ex.exchange(custBook);
27 | log.info(exhangeCustBook.getName());
28 | } catch (InterruptedException e) {
29 | e.printStackTrace();
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Exchanger/src/main/java/com.flydean/ExchangerUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.concurrent.Exchanger;
4 |
5 | /**
6 | * @author wayne
7 | * @version ExchangerUsage, 2020/4/10 10:07 下午
8 | */
9 | public class ExchangerUsage {
10 |
11 | public static void main(String[] args) {
12 | Exchanger exchanger = new Exchanger<>();
13 | // Starting two threads
14 | new Thread(new ExchangerOne(exchanger)).start();
15 | new Thread(new ExchangerTwo(exchanger)).start();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/ExecutorService/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | ExecutorService
13 |
14 |
15 |
--------------------------------------------------------------------------------
/ExecutorService/src/main/java/com/flydean/ExecutorServiceUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.concurrent.*;
6 |
7 | /**
8 | * @author wayne
9 | * @version ExecutorServiceUsage, 2020/3/1 11:28 下午
10 | */
11 | public class ExecutorServiceUsage {
12 |
13 |
14 |
15 |
16 | public static void main(String[] args) throws ExecutionException, InterruptedException {
17 |
18 | ExecutorService executor = Executors.newFixedThreadPool(10);
19 |
20 | ExecutorService executorService =
21 | new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
22 | new LinkedBlockingQueue());
23 |
24 |
25 | Runnable runnableTask = () -> {
26 | try {
27 | TimeUnit.MILLISECONDS.sleep(300);
28 | } catch (InterruptedException e) {
29 | e.printStackTrace();
30 | }
31 | };
32 |
33 | Callable callableTask = () -> {
34 | TimeUnit.MILLISECONDS.sleep(300);
35 | return "Task's execution";
36 | };
37 |
38 | List> callableTasks = new ArrayList<>();
39 | callableTasks.add(callableTask);
40 | callableTasks.add(callableTask);
41 | callableTasks.add(callableTask);
42 |
43 | executorService.execute(runnableTask);
44 |
45 | Future future =
46 | executorService.submit(callableTask);
47 |
48 | String result = executorService.invokeAny(callableTasks);
49 |
50 | List> futures = executorService.invokeAll(callableTasks);
51 |
52 | executorService.shutdown();
53 |
54 | List notExecutedTasks = executorService.shutdownNow();
55 |
56 |
57 | executorService.shutdown();
58 | try {
59 | if (!executorService.awaitTermination(800, TimeUnit.MILLISECONDS)) {
60 | executorService.shutdownNow();
61 | }
62 | } catch (InterruptedException e) {
63 | executorService.shutdownNow();
64 | }
65 |
66 |
67 |
68 |
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/ExecutorServiceShutdown/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | ExecutorServiceShutdown
13 |
14 |
15 |
--------------------------------------------------------------------------------
/ExecutorServiceShutdown/src/main/java/com/flydean/ShutdownNowUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.concurrent.Callable;
6 | import java.util.concurrent.ExecutorService;
7 | import java.util.concurrent.Executors;
8 | import java.util.concurrent.TimeUnit;
9 |
10 | /**
11 | * @author wayne
12 | * @version ShutdownNowUsage, 2020/3/25 7:56 下午
13 | */
14 | public class ShutdownNowUsage {
15 |
16 | public void useShutdownNow() throws InterruptedException {
17 | TrackingExecutor trackingExecutor=new TrackingExecutor(Executors.newCachedThreadPool());
18 |
19 | Runnable runnableTask = () -> {
20 | try {
21 | TimeUnit.MILLISECONDS.sleep(300);
22 | } catch (InterruptedException e) {
23 | e.printStackTrace();
24 | }
25 | };
26 |
27 | trackingExecutor.submit(runnableTask);
28 | List notrunList=trackingExecutor.shutdownNow();
29 | if(trackingExecutor.awaitTermination(800, TimeUnit.SECONDS)){
30 | List runButCancelledList= trackingExecutor.getCancelledTask();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/ExecutorServiceShutdown/src/main/java/com/flydean/ShutdownUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.concurrent.ExecutorService;
4 | import java.util.concurrent.Executors;
5 | import java.util.concurrent.Future;
6 | import java.util.concurrent.TimeUnit;
7 |
8 | /**
9 | * @author wayne
10 | * @version ShutdownUsage, 2020/3/25 7:40 下午
11 | */
12 | public class ShutdownUsage {
13 |
14 | public void useShutdown() throws InterruptedException {
15 | ExecutorService executor = Executors.newFixedThreadPool(10);
16 |
17 | Runnable runnableTask = () -> {
18 | try {
19 | TimeUnit.MILLISECONDS.sleep(300);
20 | } catch (InterruptedException e) {
21 | e.printStackTrace();
22 | }
23 | };
24 |
25 | executor.submit(runnableTask);
26 | executor.shutdown();
27 | executor.awaitTermination(800, TimeUnit.MILLISECONDS);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/ExecutorServiceShutdown/src/main/java/com/flydean/TrackingExecutor.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.*;
4 | import java.util.concurrent.AbstractExecutorService;
5 | import java.util.concurrent.ExecutorService;
6 | import java.util.concurrent.TimeUnit;
7 |
8 | /**
9 | * @author wayne
10 | * @version TrackingExecutor, 2020/3/25 7:57 下午
11 | */
12 | public class TrackingExecutor extends AbstractExecutorService {
13 | private final ExecutorService executorService;
14 | private final Set taskCancelledAtShutdown= Collections.synchronizedSet(new HashSet());
15 |
16 | public TrackingExecutor(ExecutorService executorService){
17 | this.executorService=executorService;
18 | }
19 | @Override
20 | public void shutdown() {
21 | executorService.shutdown();
22 | }
23 |
24 | @Override
25 | public List shutdownNow() {
26 | return executorService.shutdownNow();
27 | }
28 |
29 | @Override
30 | public boolean isShutdown() {
31 | return executorService.isShutdown();
32 | }
33 |
34 | @Override
35 | public boolean isTerminated() {
36 | return executorService.isTerminated();
37 | }
38 |
39 | @Override
40 | public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
41 | return executorService.awaitTermination(timeout,unit);
42 | }
43 |
44 | @Override
45 | public void execute(Runnable command) {
46 | executorService.execute(() -> {
47 | try {
48 | command.run();
49 | }finally {
50 | if(isShutdown() && Thread.currentThread().isInterrupted()){
51 | taskCancelledAtShutdown.add(command);
52 | }
53 | }
54 | });
55 | }
56 |
57 | public List getCancelledTask(){
58 | if(! executorService.isTerminated()){
59 | throw new IllegalStateException("executorService is not terminated");
60 | }
61 | return new ArrayList<>(taskCancelledAtShutdown);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Locks/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | Locks
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Locks/src/main/java/com.flydean/ConditionUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.Stack;
4 | import java.util.concurrent.locks.Condition;
5 | import java.util.concurrent.locks.Lock;
6 | import java.util.concurrent.locks.ReentrantLock;
7 |
8 | /**
9 | * @author wayne
10 | * @version ConditionUsage, 2020/3/10 10:33 上午
11 | */
12 | public class ConditionUsage {
13 | final Lock lock = new ReentrantLock();
14 | final Condition notFull = lock.newCondition();
15 | final Condition notEmpty = lock.newCondition();
16 |
17 | final Object[] items = new Object[100];
18 | int putptr, takeptr, count;
19 |
20 | public void put(Object x) throws InterruptedException {
21 | lock.lock();
22 | try {
23 | while (count == items.length)
24 | notFull.await();
25 | items[putptr] = x;
26 | if (++putptr == items.length) putptr = 0;
27 | ++count;
28 | notEmpty.signal();
29 | } finally {
30 | lock.unlock();
31 | }
32 | }
33 |
34 | public Object take() throws InterruptedException {
35 | lock.lock();
36 | try {
37 | while (count == 0)
38 | notEmpty.await();
39 | Object x = items[takeptr];
40 | if (++takeptr == items.length) takeptr = 0;
41 | --count;
42 | notFull.signal();
43 | return x;
44 | } finally {
45 | lock.unlock();
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Locks/src/main/java/com.flydean/ReentrantLockUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.concurrent.TimeUnit;
4 | import java.util.concurrent.locks.ReentrantLock;
5 |
6 | /**
7 | * @author wayne
8 | * @version ReentrantLockUsage, 2020/3/10 8:51 上午
9 | */
10 | public class ReentrantLockUsage {
11 | ReentrantLock lock = new ReentrantLock();
12 | int counter = 0;
13 |
14 | public static void main(String[] args) throws InterruptedException {
15 | ReentrantLockUsage reentrantLockUsage=new ReentrantLockUsage();
16 | reentrantLockUsage.perform();
17 | reentrantLockUsage.performTryLock();
18 | }
19 |
20 | public void perform() {
21 |
22 | lock.lock();
23 | try {
24 | counter++;
25 | } finally {
26 | lock.unlock();
27 | }
28 | }
29 |
30 | public void performTryLock() throws InterruptedException {
31 | boolean isLockAcquired = lock.tryLock(1, TimeUnit.SECONDS);
32 |
33 | if(isLockAcquired) {
34 | try {
35 | counter++;
36 | } finally {
37 | lock.unlock();
38 | }
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Locks/src/main/java/com.flydean/ReentrantReadWriteLockUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 | import java.util.concurrent.locks.Lock;
6 | import java.util.concurrent.locks.ReadWriteLock;
7 | import java.util.concurrent.locks.ReentrantReadWriteLock;
8 |
9 | /**
10 | * @author wayne
11 | * @version ReentrantReadWriteLock, 2020/3/10 9:02 上午
12 | */
13 | public class ReentrantReadWriteLockUsage {
14 |
15 | Map syncHashMap = new HashMap<>();
16 | ReadWriteLock lock = new ReentrantReadWriteLock();
17 |
18 | Lock writeLock = lock.writeLock();
19 |
20 | public void put(String key, String value) {
21 | try {
22 | writeLock.lock();
23 | syncHashMap.put(key, value);
24 | } finally {
25 | writeLock.unlock();
26 | }
27 | }
28 |
29 | public String remove(String key){
30 | try {
31 | writeLock.lock();
32 | return syncHashMap.remove(key);
33 | } finally {
34 | writeLock.unlock();
35 | }
36 | }
37 |
38 | Lock readLock = lock.readLock();
39 | public String get(String key){
40 | try {
41 | readLock.lock();
42 | return syncHashMap.get(key);
43 | } finally {
44 | readLock.unlock();
45 | }
46 | }
47 |
48 | public boolean containsKey(String key) {
49 | try {
50 | readLock.lock();
51 | return syncHashMap.containsKey(key);
52 | } finally {
53 | readLock.unlock();
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Locks/src/main/java/com.flydean/StampedLockUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.concurrent.locks.StampedLock;
4 |
5 | /**
6 | * @author wayne
7 | * @version StampedLockUsage, 2020/3/10 9:06 上午
8 | */
9 | public class StampedLockUsage {
10 |
11 | private double x, y;
12 | private final StampedLock sl = new StampedLock();
13 |
14 | void move(double deltaX, double deltaY) { // an exclusively locked method
15 | long stamp = sl.writeLock();
16 | try {
17 | x += deltaX;
18 | y += deltaY;
19 | } finally {
20 | sl.unlockWrite(stamp);
21 | }
22 | }
23 |
24 | double distanceFromOrigin() { // A read-only method
25 | long stamp = sl.tryOptimisticRead();
26 | double currentX = x, currentY = y;
27 | if (!sl.validate(stamp)) {
28 | stamp = sl.readLock();
29 | try {
30 | currentX = x;
31 | currentY = y;
32 | } finally {
33 | sl.unlockRead(stamp);
34 | }
35 | }
36 | return Math.sqrt(currentX * currentX + currentY * currentY);
37 | }
38 |
39 | void moveIfAtOrigin(double newX, double newY) { // upgrade
40 | // Could instead start with optimistic, not read mode
41 | long stamp = sl.readLock();
42 | try {
43 | while (x == 0.0 && y == 0.0) {
44 | long ws = sl.tryConvertToWriteLock(stamp);
45 | if (ws != 0L) {
46 | stamp = ws;
47 | x = newX;
48 | y = newY;
49 | break;
50 | }
51 | else {
52 | sl.unlockRead(stamp);
53 | stamp = sl.writeLock();
54 | }
55 | }
56 | } finally {
57 | sl.unlock(stamp);
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/MemoizedCalculate/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | MemoizedCalculate
13 |
14 |
15 |
--------------------------------------------------------------------------------
/MemoizedCalculate/src/main/java/com.flydean/Calculator.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version calculator, 2020/3/22 12:44 下午
6 | */
7 | public interface Calculator {
8 |
9 | V calculate(A arg) throws InterruptedException;
10 | }
11 |
--------------------------------------------------------------------------------
/MemoizedCalculate/src/main/java/com.flydean/MemoizedCalculator1.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | /**
7 | * @author wayne
8 | * @version MemoizedCalculator1, 2020/3/22 12:47 下午
9 | */
10 | public class MemoizedCalculator1 implements Calculator {
11 |
12 | private final Map cache= new HashMap();
13 | private final Calculator calculator;
14 |
15 | public MemoizedCalculator1(Calculator calculator){
16 | this.calculator=calculator;
17 | }
18 | @Override
19 | public synchronized V calculate(A arg) throws InterruptedException {
20 | V result= cache.get(arg);
21 | if( result ==null ){
22 | result= calculator.calculate(arg);
23 | cache.put(arg, result);
24 | }
25 | return result;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/MemoizedCalculate/src/main/java/com.flydean/MemoizedCalculator2.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.Map;
4 | import java.util.concurrent.ConcurrentHashMap;
5 |
6 | /**
7 | * @author wayne
8 | * @version MemoizedCalculator1, 2020/3/22 12:47 下午
9 | */
10 | public class MemoizedCalculator2 implements Calculator {
11 |
12 | private final Map cache= new ConcurrentHashMap<>();
13 | private final Calculator calculator;
14 |
15 | public MemoizedCalculator2(Calculator calculator){
16 | this.calculator=calculator;
17 | }
18 | @Override
19 | public V calculate(A arg) throws InterruptedException {
20 | V result= cache.get(arg);
21 | if( result ==null ){
22 | result= calculator.calculate(arg);
23 | cache.put(arg, result);
24 | }
25 | return result;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/MemoizedCalculate/src/main/java/com.flydean/MemoizedCalculator3.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.util.Map;
6 | import java.util.concurrent.*;
7 |
8 | /**
9 | * @author wayne
10 | * @version MemoizedCalculator1, 2020/3/22 12:47 下午
11 | */
12 | @Slf4j
13 | public class MemoizedCalculator3 implements Calculator {
14 |
15 | private final Map> cache= new ConcurrentHashMap<>();
16 | private final Calculator calculator;
17 |
18 | public MemoizedCalculator3(Calculator calculator){
19 | this.calculator=calculator;
20 | }
21 | @Override
22 | public V calculate(A arg) throws InterruptedException {
23 | Future future= cache.get(arg);
24 | V result=null;
25 | if( future ==null ){
26 | Callable callable= new Callable() {
27 | @Override
28 | public V call() throws Exception {
29 | return calculator.calculate(arg);
30 | }
31 | };
32 | FutureTask futureTask= new FutureTask<>(callable);
33 | future= futureTask;
34 | cache.put(arg, futureTask);
35 | futureTask.run();
36 | }
37 | try {
38 | result= future.get();
39 | } catch (ExecutionException e) {
40 | log.error(e.getMessage(),e);
41 | }
42 | return result;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/MemoizedCalculate/src/main/java/com.flydean/MemoizedCalculator4.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.util.Map;
6 | import java.util.concurrent.*;
7 |
8 | /**
9 | * @author wayne
10 | * @version MemoizedCalculator1, 2020/3/22 12:47 下午
11 | */
12 | @Slf4j
13 | public class MemoizedCalculator4 implements Calculator {
14 |
15 | private final Map> cache= new ConcurrentHashMap<>();
16 | private final Calculator calculator;
17 |
18 | public MemoizedCalculator4(Calculator calculator){
19 | this.calculator=calculator;
20 | }
21 | @Override
22 | public V calculate(A arg) throws InterruptedException {
23 | while (true) {
24 | Future future = cache.get(arg);
25 | V result = null;
26 | if (future == null) {
27 | Callable callable = new Callable() {
28 | @Override
29 | public V call() throws Exception {
30 | return calculator.calculate(arg);
31 | }
32 | };
33 | FutureTask futureTask = new FutureTask<>(callable);
34 | future = cache.putIfAbsent(arg, futureTask);
35 | if (future == null) {
36 | future = futureTask;
37 | futureTask.run();
38 | }
39 |
40 | try {
41 | result = future.get();
42 | } catch (CancellationException e) {
43 | log.error(e.getMessage(), e);
44 | cache.remove(arg, future);
45 | } catch (ExecutionException e) {
46 | log.error(e.getMessage(), e);
47 | }
48 | return result;
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Phaser/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | Phaser
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Phaser/src/main/java/com.flydean/PhaserTask.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.List;
4 | import java.util.concurrent.Phaser;
5 |
6 | /**
7 | * @author wayne
8 | * @version PhaserTask, 2020/3/18 9:01 上午
9 | */
10 | public class PhaserTask {
11 |
12 | void runTasks(List tasks) {
13 | final Phaser phaser = new Phaser(1); // "1" to register self
14 | // create and start threads
15 | for (final Runnable task : tasks) {
16 | phaser.register();
17 | new Thread() {
18 | public void run() {
19 | phaser.arriveAndAwaitAdvance(); // await all creation
20 | task.run();
21 | }
22 | }.start();
23 | }
24 |
25 | // allow threads to start and deregister self
26 | phaser.arriveAndDeregister();
27 | }
28 |
29 | void startTasks(List tasks, final int iterations) {
30 | final Phaser phaser = new Phaser() {
31 | protected boolean onAdvance(int phase, int registeredParties) {
32 | return phase >= iterations || registeredParties == 0;
33 | }
34 | };
35 | phaser.register();
36 | for (final Runnable task : tasks) {
37 | phaser.register();
38 | new Thread() {
39 | public void run() {
40 | do {
41 | task.run();
42 | phaser.arriveAndAwaitAdvance();
43 | } while (!phaser.isTerminated());
44 | }
45 | }.start();
46 | }
47 | phaser.arriveAndDeregister(); // deregister self, don't wait
48 | }
49 |
50 |
51 | void awaitPhase(Phaser phaser, int phase) {
52 | int p = phaser.register(); // assumes caller not already registered
53 | while (p < phase) {
54 | if (phaser.isTerminated()) {
55 | // ... deal with unexpected termination
56 | }
57 | else {
58 | p = phaser.arriveAndAwaitAdvance();
59 | }
60 | }
61 | phaser.arriveAndDeregister();
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/Phaser/src/main/java/com.flydean/PhaserUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.concurrent.Phaser;
4 |
5 | /**
6 | * @author wayne
7 | * @version PhaserUsage, 2020/3/17 10:45 下午
8 | */
9 | public class PhaserUsage implements Runnable {
10 | private String threadName;
11 | private Phaser ph;
12 |
13 | PhaserUsage(String threadName, Phaser ph) {
14 | this.threadName = threadName;
15 | this.ph = ph;
16 | ph.register();
17 | }
18 |
19 | @Override
20 | public void run() {
21 | ph.arriveAndAwaitAdvance();
22 | try {
23 | Thread.sleep(20);
24 | } catch (InterruptedException e) {
25 | e.printStackTrace();
26 | }
27 | ph.arriveAndDeregister();
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/RCU/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | RCU
13 |
14 |
15 |
--------------------------------------------------------------------------------
/RCU/src/main/java/com/flydean/RCU.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.concurrent.atomic.AtomicLong;
4 | import java.util.concurrent.atomic.AtomicLongArray;
5 |
6 | /**
7 | * @author wayne
8 | * @version RCU, 2020/5/11 1:37 下午
9 | */
10 | public class RCU {
11 | final static long NOT_READING = Long.MAX_VALUE;
12 | final static int MAX_THREADS = 128;
13 | final AtomicLong reclaimerVersion = new AtomicLong(0);
14 | final AtomicLongArray readersVersion = new AtomicLongArray(MAX_THREADS);
15 |
16 | public RCU() {
17 | for (int i=0; i < MAX_THREADS; i++) readersVersion.set(i, NOT_READING);
18 | }
19 |
20 | public static int getTID() {
21 | return (int)(Thread.currentThread().getId() % MAX_THREADS);
22 | }
23 |
24 | public void read_lock(final int tid) { // rcu_read_lock()
25 | final long rv = reclaimerVersion.get();
26 | readersVersion.set(tid, rv);
27 | final long nrv = reclaimerVersion.get();
28 | if (rv != nrv) readersVersion.lazySet(tid, nrv);
29 | }
30 |
31 | public void read_unlock(final int tid) { // rcu_read_unlock()
32 | readersVersion.set(tid, NOT_READING);
33 | }
34 |
35 | public void synchronize_rcu() {
36 | final long waitForVersion = reclaimerVersion.incrementAndGet();
37 | for (int i=0; i < MAX_THREADS; i++) {
38 | while (readersVersion.get(i) < waitForVersion) { } // spin
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # learn-java-concurrency
2 |
3 | 这是我写的java多线程方面的教程.
4 |
5 | 如果喜欢的话,请大家 star 一下,谢谢
6 |
7 | # 系列教程
8 |
9 | * [java.util.concurrent简介](http://www.flydean.com/java-util-concurrent-overview/)
10 | * [java并发中的Synchronized关键词](http://www.flydean.com/java-concurrent-synchronized/)
11 | * [java中的Volatile关键字使用](http://www.flydean.com/java-concurrent-volatile/)
12 | * [java中wait和sleep的区别](http://www.flydean.com/java-wait-sleep/)
13 | * [java中Future的使用](http://www.flydean.com/java-future/)
14 | * [java并发中ExecutorService的使用](http://www.flydean.com/java-executorservice/)
15 | * [java中Runnable和Callable的区别](http://www.flydean.com/java-runnable-callable/)
16 | * [java中ThreadLocal的使用](http://www.flydean.com/java-threadlocal/)
17 | * [java中线程的生命周期](http://www.flydean.com/java-thread-lifecycle/)
18 | * [java中join的使用](http://www.flydean.com/java-join/)
19 | * [怎么在java中关闭一个thread](http://www.flydean.com/java-kill-thread/)
20 | * [java中的Atomic类](http://www.flydean.com/java-atomic/)
21 | * [java中interrupt,interrupted和isInterrupted的区别](http://www.flydean.com/java-interrupt/)
22 | * [java中的daemon thread](http://www.flydean.com/java-daemon-thread/)
23 | * [java中ThreadPool的介绍和使用](http://www.flydean.com/java-threadpool/)
24 | * [java中的fork join框架](http://www.flydean.com/java-fork-join/)
25 | * [java中Locks的使用](http://www.flydean.com/java-locks/)
26 | * [java并发中CountDownLatch的使用](http://www.flydean.com/java-countdownlatch/)
27 | * [java中CyclicBarrier的使用](http://www.flydean.com/java-cyclicbarrier/)
28 | * [在java中使用JMH(Java Microbenchmark Harness)做性能测试](http://www.flydean.com/java-jmh/)
29 | * [java中ThreadLocalRandom的使用](http://www.flydean.com/java-threadlocalrandom/)
30 | * [java中FutureTask的使用](http://www.flydean.com/java-futuretask/)
31 | * [关于CompletableFuture的一切,看这篇文章就够了](http://www.flydean.com/java-completablefuture/)
32 | * [java多线程之Phaser](http://www.flydean.com/java-phaser/)
33 | * [java中使用Semaphore构建阻塞对象池](http://www.flydean.com/java-semaphore/)
34 | * [在java中构建高效的结果缓存](http://www.flydean.com/java-memoizedcalculator/)
35 | * [java中CompletionService的使用](http://www.flydean.com/java-completionservice/)
36 | * [使用ExecutorService来停止线程服务](http://www.flydean.com/java-shutdown-executorservice/)
37 | * [我们的线程被饿死了](http://www.flydean.com/java-starvationdeadlock/)
38 | * [java中有界队列的饱和策略(reject policy)](http://www.flydean.com/java-reject-policy/)
39 | * [由于不当的执行顺序导致的死锁](http://www.flydean.com/java-lock-ordering-deadlock/)
40 | * [同步类的基础AbstractQueuedSynchronizer(AQS)](http://www.flydean.com/java-aqs/)
41 | * [非阻塞同步机制和CAS](http://www.flydean.com/java-cas/)
42 | * [非阻塞算法(Lock-Free)的实现](http://www.flydean.com/java-lock-free/)
43 | * [java内存模型(JMM)和happens-before](http://www.flydean.com/java-jmm-happens-before/)
44 |
--------------------------------------------------------------------------------
/Semaphore/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | Semaphore
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Semaphore/src/main/java/com.flydean/SemaphoreUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.Collections;
4 | import java.util.HashSet;
5 | import java.util.Set;
6 | import java.util.concurrent.Semaphore;
7 |
8 | /**
9 | * @author wayne
10 | * @version SemaphoreUsage, 2020/3/21 5:00 下午
11 | */
12 | public class SemaphoreUsage {
13 |
14 | private final Set set;
15 | private final Semaphore sem;
16 |
17 | public SemaphoreUsage(int bound){
18 | this.set = Collections.synchronizedSet(new HashSet());
19 | sem= new Semaphore(bound);
20 | }
21 |
22 | public boolean add (T o) throws InterruptedException{
23 | sem.acquire();
24 | boolean wasAdded = false;
25 | try{
26 | wasAdded=set.add(o);
27 | return wasAdded;
28 | }finally {
29 | if(!wasAdded){
30 | sem.release();
31 | }
32 | }
33 | }
34 |
35 | public boolean remove(Object o){
36 | boolean wasRemoved = set.remove(o);
37 | if(wasRemoved){
38 | sem.release();
39 | }
40 | return wasRemoved;
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/Synchronized/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | Synchronized
13 |
14 |
15 | junit
16 | junit
17 | 4.13.1
18 | test
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Synchronized/src/main/java/com/flydean/SynchronizedMethods.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @author wayne
7 | * @version SynchronizedMethods, 2020/2/25 10:10 下午
8 | */
9 | @Data
10 | public class SynchronizedMethods {
11 |
12 | private int sum = 0;
13 |
14 | public static int staticSum=0;
15 |
16 | public void calculate() {
17 | setSum(getSum() + 1);
18 | }
19 |
20 | public synchronized void synchronisedCalculate() {
21 | setSum(getSum() + 1);
22 | }
23 |
24 | public static synchronized void syncStaticCalculate() {
25 | staticSum = staticSum + 1;
26 | }
27 |
28 | public void performSynchronizedTask() {
29 | synchronized (this) {
30 | setSum(getSum() + 1);
31 | }
32 | }
33 |
34 | public static void performStaticSyncTask(){
35 | synchronized (SynchronizedMethods.class) {
36 | staticSum = staticSum + 1;
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Synchronized/src/test/java/com/flydean/SynchronizedMethodsTest.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import org.junit.Test;
4 |
5 | import java.util.concurrent.ExecutorService;
6 | import java.util.concurrent.Executors;
7 | import java.util.concurrent.TimeUnit;
8 | import java.util.stream.IntStream;
9 |
10 | import static org.junit.Assert.assertEquals;
11 |
12 | /**
13 | * @author wayne
14 | * @version SynchronizedMethodsTest, 2020/2/25 10:11 下午
15 | */
16 | public class SynchronizedMethodsTest {
17 |
18 |
19 | @Test
20 | public void givenMultiThread_whenNonSyncMethod() throws InterruptedException {
21 | ExecutorService service = Executors.newFixedThreadPool(3);
22 | SynchronizedMethods summation = new SynchronizedMethods();
23 |
24 | IntStream.range(0, 1000)
25 | .forEach(count -> service.submit(summation::calculate));
26 | service.shutdown();
27 | service.awaitTermination(1000, TimeUnit.MILLISECONDS);
28 |
29 | assertEquals(1000, summation.getSum());
30 | }
31 |
32 | @Test
33 | public void givenMultiThread_whenMethodSync() throws InterruptedException {
34 | ExecutorService service = Executors.newFixedThreadPool(3);
35 | SynchronizedMethods method = new SynchronizedMethods();
36 |
37 | IntStream.range(0, 1000)
38 | .forEach(count -> service.submit(method::synchronisedCalculate));
39 | service.shutdown();
40 | service.awaitTermination(1000, TimeUnit.MILLISECONDS);
41 |
42 | assertEquals(1000, method.getSum());
43 | }
44 |
45 | @Test
46 | public void givenMultiThread_whenStaticSyncMethod() throws InterruptedException {
47 | ExecutorService service = Executors.newCachedThreadPool();
48 |
49 | IntStream.range(0, 1000)
50 | .forEach(count ->
51 | service.submit(SynchronizedMethods::syncStaticCalculate));
52 | service.shutdown();
53 | service.awaitTermination(100, TimeUnit.MILLISECONDS);
54 |
55 | assertEquals(1000, SynchronizedMethods.staticSum);
56 | }
57 |
58 | @Test
59 | public void givenMultiThread_whenBlockSync() throws InterruptedException {
60 | ExecutorService service = Executors.newFixedThreadPool(3);
61 | SynchronizedMethods synchronizedBlocks = new SynchronizedMethods();
62 |
63 | IntStream.range(0, 1000)
64 | .forEach(count ->
65 | service.submit(synchronizedBlocks::performSynchronizedTask));
66 | service.shutdown();
67 | service.awaitTermination(100, TimeUnit.MILLISECONDS);
68 |
69 | assertEquals(1000, synchronizedBlocks.getSum());
70 | }
71 |
72 | @Test
73 | public void givenMultiThread_whenStaticSyncBlock() throws InterruptedException {
74 | ExecutorService service = Executors.newCachedThreadPool();
75 |
76 | IntStream.range(0, 1000)
77 | .forEach(count ->
78 | service.submit(SynchronizedMethods::performStaticSyncTask));
79 | service.shutdown();
80 | service.awaitTermination(100, TimeUnit.MILLISECONDS);
81 |
82 | assertEquals(1000, SynchronizedMethods.staticSum);
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/ThreadLocal/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | ThreadLocal
13 |
14 |
15 | junit
16 | junit
17 | 4.13.1
18 | test
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/ThreadLocal/src/main/java/com/flydean/Context.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version Context, 2020/3/2 10:57 上午
6 | */
7 | public class Context {
8 | private String userName;
9 |
10 | public Context(String userName) {
11 | this.userName = userName;
12 | }
13 | }
--------------------------------------------------------------------------------
/ThreadLocal/src/main/java/com/flydean/SharedMapWithUserContext.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.Map;
4 | import java.util.concurrent.ConcurrentHashMap;
5 |
6 | /**
7 | * @author wayne
8 | * @version SharedMapWithUserContext, 2020/3/2 10:57 上午
9 | */
10 | public class SharedMapWithUserContext implements Runnable {
11 |
12 | public static Map userContextPerUserId
13 | = new ConcurrentHashMap<>();
14 | private Integer userId;
15 | private UserRepository userRepository = new UserRepository();
16 |
17 | public SharedMapWithUserContext(int i) {
18 | this.userId=i;
19 | }
20 |
21 | @Override
22 | public void run() {
23 | String userName = userRepository.getUserNameForUserId(userId);
24 | userContextPerUserId.put(userId, new Context(userName));
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ThreadLocal/src/main/java/com/flydean/ThreadLocalUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version ThreadLocalUsage, 2020/3/2 10:41 上午
6 | */
7 | public class ThreadLocalUsage {
8 |
9 | public static void main(String[] args) {
10 | ThreadLocal threadLocalValue = new ThreadLocal<>();
11 | threadLocalValue.set(1);
12 | Integer result = threadLocalValue.get();
13 |
14 | ThreadLocal threadLocal = ThreadLocal.withInitial(() -> 1);
15 |
16 | threadLocal.remove();
17 |
18 |
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/ThreadLocal/src/main/java/com/flydean/ThreadLocalWithUserContext.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version ThreadLocalWithUserContext, 2020/3/2 11:15 上午
6 | */
7 | public class ThreadLocalWithUserContext implements Runnable {
8 |
9 | private static ThreadLocal userContext
10 | = new ThreadLocal<>();
11 | private Integer userId;
12 | private UserRepository userRepository = new UserRepository();
13 |
14 | public ThreadLocalWithUserContext(int i) {
15 | this.userId=i;
16 | }
17 |
18 | @Override
19 | public void run() {
20 | String userName = userRepository.getUserNameForUserId(userId);
21 | userContext.set(new Context(userName));
22 | System.out.println("thread context for given userId: "
23 | + userId + " is: " + userContext.get());
24 | }
25 |
26 | }
--------------------------------------------------------------------------------
/ThreadLocal/src/main/java/com/flydean/UserRepository.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version UserRepository, 2020/3/2 11:05 上午
6 | */
7 | public class UserRepository {
8 | public String getUserNameForUserId(Integer userId) {
9 | return userId.toString();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/ThreadLocal/src/test/java/com/flydean/ShareMapWithUserContextTest.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.assertEquals;
6 |
7 | /**
8 | * @author wayne
9 | * @version ShareMapWithUserContextTest, 2020/3/2 11:11 上午
10 | */
11 | public class ShareMapWithUserContextTest {
12 |
13 | @Test
14 | public void testWithMap(){
15 | SharedMapWithUserContext firstUser = new SharedMapWithUserContext(1);
16 | SharedMapWithUserContext secondUser = new SharedMapWithUserContext(2);
17 | new Thread(firstUser).start();
18 | new Thread(secondUser).start();
19 | assertEquals(SharedMapWithUserContext.userContextPerUserId.size(), 2);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/ThreadLocal/src/test/java/com/flydean/ThreadLocalWithUserContextTest.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * @author wayne
7 | * @version ThreadLocalWithUserContextTest, 2020/3/2 11:16 上午
8 | */
9 | public class ThreadLocalWithUserContextTest {
10 |
11 | @Test
12 | public void testWithThreadLocal(){
13 | ThreadLocalWithUserContext firstUser
14 | = new ThreadLocalWithUserContext(1);
15 | ThreadLocalWithUserContext secondUser
16 | = new ThreadLocalWithUserContext(2);
17 | new Thread(firstUser).start();
18 | new Thread(secondUser).start();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/ThreadLocalRandom/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | ThreadLocalRandom
13 |
14 |
15 |
16 | org.openjdk.jmh
17 | jmh-core
18 | 1.19
19 |
20 |
21 | org.openjdk.jmh
22 | jmh-generator-annprocess
23 | 1.19
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ThreadLocalRandom/src/main/java/com.flydean/RandomUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import org.openjdk.jmh.runner.Runner;
4 | import org.openjdk.jmh.runner.RunnerException;
5 | import org.openjdk.jmh.runner.options.Options;
6 | import org.openjdk.jmh.runner.options.OptionsBuilder;
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 | import java.util.Random;
11 | import java.util.concurrent.Callable;
12 | import java.util.concurrent.ExecutorService;
13 | import java.util.concurrent.Executors;
14 |
15 | /**
16 | * @author wayne
17 | * @version RandomUsage, 2020/3/14 9:16 上午
18 | */
19 | public class RandomUsage {
20 |
21 | public void testRandom() throws InterruptedException {
22 | ExecutorService executorService=Executors.newFixedThreadPool(2);
23 | Random random = new Random();
24 | List> callables = new ArrayList<>();
25 | for (int i = 0; i < 1000; i++) {
26 | callables.add(() -> {
27 | return random.nextInt();
28 | });
29 | }
30 | executorService.invokeAll(callables);
31 | }
32 |
33 | public static void main(String[] args) throws RunnerException {
34 | Options opt = new OptionsBuilder()
35 | .include(RandomUsage.class.getSimpleName())
36 | // 预热5轮
37 | .warmupIterations(5)
38 | // 度量10轮
39 | .measurementIterations(10)
40 | .forks(1)
41 | .build();
42 |
43 | new Runner(opt).run();
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/ThreadLocalRandom/src/main/java/com.flydean/ThreadLocalRandomUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import org.openjdk.jmh.annotations.Benchmark;
4 | import org.openjdk.jmh.annotations.BenchmarkMode;
5 | import org.openjdk.jmh.annotations.Mode;
6 | import org.openjdk.jmh.annotations.OutputTimeUnit;
7 | import org.openjdk.jmh.runner.Runner;
8 | import org.openjdk.jmh.runner.RunnerException;
9 | import org.openjdk.jmh.runner.options.Options;
10 | import org.openjdk.jmh.runner.options.OptionsBuilder;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 | import java.util.Random;
15 | import java.util.concurrent.*;
16 |
17 | /**
18 | * @author wayne
19 | * @version ThreadLocalRandomUsage, 2020/3/14 9:15 上午
20 | */
21 | public class ThreadLocalRandomUsage {
22 |
23 | @Benchmark
24 | @BenchmarkMode(Mode.AverageTime)
25 | @OutputTimeUnit(TimeUnit.MICROSECONDS)
26 | public void testThreadLocalRandom() throws InterruptedException {
27 | ExecutorService executorService=Executors.newFixedThreadPool(2);
28 | List> callables = new ArrayList<>();
29 | for (int i = 0; i < 1000; i++) {
30 | callables.add(() -> {
31 | return ThreadLocalRandom.current().nextInt();
32 | });
33 | }
34 | executorService.invokeAll(callables);
35 | }
36 |
37 | public static void main(String[] args) throws RunnerException {
38 | Options opt = new OptionsBuilder()
39 | .include(ThreadLocalRandomUsage.class.getSimpleName())
40 | // 预热5轮
41 | .warmupIterations(5)
42 | // 度量10轮
43 | .measurementIterations(10)
44 | .forks(1)
45 | .build();
46 |
47 | new Runner(opt).run();
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/ThreadPoolDeadlock/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | ThreadPoolDeadlock
13 |
14 |
15 | junit
16 | junit
17 | 4.13.1
18 | compile
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/ThreadPoolDeadlock/src/main/java/com/flydean/ThreadPoolDeadlock.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import org.junit.Test;
4 |
5 | import java.util.concurrent.*;
6 |
7 | /**
8 | * @author wayne
9 | * @version ThreadPoolDeadlock, 2020/3/25 9:02 下午
10 | */
11 | public class ThreadPoolDeadlock {
12 |
13 | ExecutorService executorService= Executors.newSingleThreadExecutor();
14 |
15 | public class RenderPageTask implements Callable {
16 | public String call() throws Exception{
17 | Future header, footer;
18 | header= executorService.submit(()->{
19 | return "header";
20 | });
21 | footer= executorService.submit(()->{
22 | return "footer";
23 | });
24 | return header.get()+ footer.get();
25 | }
26 | }
27 |
28 | public void submitTask(){
29 | executorService.submit(new RenderPageTask());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/accountTransferLock/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | accountTransferLock
13 |
14 |
15 |
--------------------------------------------------------------------------------
/accountTransferLock/src/main/java/com/flydean/Account.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version Account, 2020/3/26 11:30 上午
6 | */
7 | public class Account {
8 | private int amount;
9 |
10 | public int getBalance(){
11 | return amount;
12 | }
13 |
14 | public void debit(int count){
15 | amount= amount - count;
16 | }
17 |
18 | public void credit(int count){
19 | amount= amount+ count;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/accountTransferLock/src/main/java/com/flydean/AccountTransfer.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version AccountTransfer, 2020/3/26 11:29 上午
6 | */
7 | public class AccountTransfer {
8 |
9 | private static final Object lock= new Object();
10 |
11 | public void transferMoneyDeadLock(Account from,Account to, int amount) throws InsufficientAmountException {
12 | synchronized (from){
13 | synchronized (to){
14 | transfer(from,to,amount);
15 | }
16 | }
17 | }
18 |
19 | private void transfer(Account from,Account to, int amount) throws InsufficientAmountException {
20 | if(from.getBalance() < amount){
21 | throw new InsufficientAmountException();
22 | }else{
23 | from.debit(amount);
24 | to.credit(amount);
25 | }
26 | }
27 |
28 | public void transferMoney(Account from,Account to, int amount) throws InsufficientAmountException {
29 |
30 | int fromHash= System.identityHashCode(from);
31 | int toHash = System.identityHashCode(to);
32 |
33 | if(fromHash < toHash){
34 | synchronized (from){
35 | synchronized (to){
36 | transfer(from,to, amount);
37 | }
38 | }
39 | }else if(fromHash < toHash){
40 | synchronized (to){
41 | synchronized (from){
42 | transfer(from,to, amount);
43 | }
44 | }
45 | }else{
46 | synchronized (lock){
47 | synchronized (from) {
48 | synchronized (to) {
49 | transfer(from, to, amount);
50 | }
51 | }
52 | }
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/accountTransferLock/src/main/java/com/flydean/InsufficientAmountException.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version InsufficientAmountException, 2020/3/26 1:40 下午
6 | */
7 | public class InsufficientAmountException extends Throwable {
8 | }
9 |
--------------------------------------------------------------------------------
/atomic/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | atomic
13 |
14 |
15 |
--------------------------------------------------------------------------------
/atomic/src/main/java/com/flydean/AtomicCounter.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.concurrent.atomic.AtomicInteger;
4 |
5 | /**
6 | * @author wayne
7 | * @version AtomicCounter, 2020/3/4 10:59 上午
8 | */
9 | public class AtomicCounter {
10 |
11 | private final AtomicInteger counter = new AtomicInteger(0);
12 |
13 | public int getValue() {
14 | return counter.get();
15 | }
16 | public void increment() {
17 | while(true) {
18 | int existingValue = getValue();
19 | int newValue = existingValue + 1;
20 | if(counter.compareAndSet(existingValue, newValue)) {
21 | return;
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/atomic/src/main/java/com/flydean/Counter.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version Counter, 2020/3/4 10:58 上午
6 | */
7 | public class Counter {
8 |
9 | int counter;
10 |
11 | public void increment() {
12 | counter++;
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/atomic/src/main/java/com/flydean/LockCounter.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version LockCounter, 2020/3/4 10:58 上午
6 | */
7 | public class LockCounter {
8 |
9 | private volatile int counter;
10 |
11 | public synchronized void increment() {
12 | counter++;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/benchmark/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | benchmark
13 |
14 |
15 |
16 | org.openjdk.jmh
17 | jmh-core
18 | 1.19
19 |
20 |
21 | org.openjdk.jmh
22 | jmh-generator-annprocess
23 | 1.19
24 |
25 |
26 | com.google.guava
27 | guava
28 | 27.0.1-android
29 | compile
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/benchmark/src/main/java/com.flydean/BenchMarkUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.openjdk.jmh.annotations.*;
5 | import org.openjdk.jmh.runner.Runner;
6 | import org.openjdk.jmh.runner.RunnerException;
7 | import org.openjdk.jmh.runner.options.Options;
8 | import org.openjdk.jmh.runner.options.OptionsBuilder;
9 |
10 | import java.util.concurrent.TimeUnit;
11 |
12 | /**
13 | * @author wayne
14 | * @version BenchMarkUsage, 2020/3/13 10:19 下午
15 | */
16 | @Slf4j
17 | public class BenchMarkUsage {
18 |
19 | /*
20 | * JMH generates lots of synthetic code for the benchmarks for you during
21 | * the benchmark compilation. JMH can measure the benchmark methods in lots
22 | * of modes. Users may select the default benchmark mode with a special
23 | * annotation, or select/override the mode via the runtime options.
24 | *
25 | * With this scenario, we start to measure something useful. Note that our
26 | * payload code potentially throws exceptions, and we can just declare them
27 | * to be thrown. If the code throws the actual exception, the benchmark
28 | * execution will stop with an error.
29 | *
30 | * When you are puzzled with some particular behavior, it usually helps to
31 | * look into the generated code. You might see the code is doing not
32 | * something you intend it to do. Good experiments always follow up on the
33 | * experimental setup, and cross-checking the generated code is an important
34 | * part of that follow up.
35 | */
36 |
37 | /*
38 | * Mode.Throughput, as stated in its Javadoc, measures the raw throughput by
39 | * continuously calling the benchmark method in a time-bound iteration, and
40 | * counting how many times we executed the method.
41 | *
42 | * We are using the special annotation to select the units to measure in,
43 | * although you can use the default.
44 | */
45 |
46 | @Benchmark
47 | @BenchmarkMode(Mode.Throughput)
48 | @OutputTimeUnit(TimeUnit.SECONDS)
49 | public void measureThroughput() throws InterruptedException {
50 | TimeUnit.MILLISECONDS.sleep(100);
51 | }
52 |
53 | /*
54 | * Mode.AverageTime measures the average execution time, and it does it
55 | * in the way similar to Mode.Throughput.
56 | *
57 | * Some might say it is the reciprocal throughput, and it really is.
58 | * There are workloads where measuring times is more convenient though.
59 | */
60 |
61 | @Benchmark
62 | @BenchmarkMode(Mode.AverageTime)
63 | @OutputTimeUnit(TimeUnit.MICROSECONDS)
64 | public void measureAvgTime() throws InterruptedException {
65 | TimeUnit.MILLISECONDS.sleep(100);
66 | }
67 |
68 | /*
69 | * Mode.SampleTime samples the execution time. With this mode, we are
70 | * still running the method in a time-bound iteration, but instead of
71 | * measuring the total time, we measure the time spent in *some* of
72 | * the benchmark method calls.
73 | *
74 | * This allows us to infer the distributions, percentiles, etc.
75 | *
76 | * JMH also tries to auto-adjust sampling frequency: if the method
77 | * is long enough, you will end up capturing all the samples.
78 | */
79 | @Benchmark
80 | @BenchmarkMode(Mode.SampleTime)
81 | @OutputTimeUnit(TimeUnit.MICROSECONDS)
82 | public void measureSamples() throws InterruptedException {
83 | TimeUnit.MILLISECONDS.sleep(100);
84 | }
85 |
86 | /*
87 | * Mode.SingleShotTime measures the single method invocation time. As the Javadoc
88 | * suggests, we do only the single benchmark method invocation. The iteration
89 | * time is meaningless in this mode: as soon as benchmark method stops, the
90 | * iteration is over.
91 | *
92 | * This mode is useful to do cold startup tests, when you specifically
93 | * do not want to call the benchmark method continuously.
94 | */
95 | @Benchmark
96 | @BenchmarkMode(Mode.SingleShotTime)
97 | @OutputTimeUnit(TimeUnit.MICROSECONDS)
98 | public void measureSingleShot() throws InterruptedException {
99 | TimeUnit.MILLISECONDS.sleep(100);
100 | }
101 |
102 | /*
103 | * We can also ask for multiple benchmark modes at once. All the tests
104 | * above can be replaced with just a single test like this:
105 | */
106 | @Benchmark
107 | @BenchmarkMode({Mode.Throughput, Mode.AverageTime, Mode.SampleTime, Mode.SingleShotTime})
108 | @OutputTimeUnit(TimeUnit.MICROSECONDS)
109 | public void measureMultiple() throws InterruptedException {
110 | TimeUnit.MILLISECONDS.sleep(100);
111 | }
112 |
113 | /*
114 | * Or even...
115 | */
116 |
117 | @Benchmark
118 | @BenchmarkMode(Mode.All)
119 | @Fork(value = 1, warmups = 2)
120 | @Warmup(iterations = 5)
121 | @OutputTimeUnit(TimeUnit.MICROSECONDS)
122 | public void measureAll() throws InterruptedException {
123 | TimeUnit.MILLISECONDS.sleep(100);
124 | }
125 |
126 | /*
127 | * ============================== HOW TO RUN THIS TEST: ====================================
128 | *
129 | * You are expected to see the different run modes for the same benchmark.
130 | * Note the units are different, scores are consistent with each other.
131 | *
132 | * You can run this test:
133 | *
134 | * a) Via the command line:
135 | * $ mvn clean install
136 | * $ java -jar target/benchmarks.jar JMHSample_02 -f 1
137 | * (we requested a single fork; there are also other options, see -h)
138 | *
139 | * b) Via the Java API:
140 | * (see the JMH homepage for possible caveats when running from IDE:
141 | * http://openjdk.java.net/projects/code-tools/jmh/)
142 | */
143 |
144 | public static void main(String[] args) throws RunnerException {
145 | Options opt = new OptionsBuilder()
146 | .include(BenchMarkUsage.class.getSimpleName())
147 | // .include(BenchMarkUsage.class.getSimpleName()+".*measureAll*")
148 | // 预热5轮
149 | .warmupIterations(3)
150 | // 度量10轮
151 | .measurementIterations(5)
152 | .forks(1)
153 | .build();
154 |
155 | new Runner(opt).run();
156 | }
157 |
158 | }
159 |
--------------------------------------------------------------------------------
/benchmark/src/main/java/com.flydean/StateUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import com.google.common.hash.Hasher;
4 | import com.google.common.hash.Hashing;
5 | import org.openjdk.jmh.annotations.*;
6 | import org.openjdk.jmh.runner.Runner;
7 | import org.openjdk.jmh.runner.RunnerException;
8 | import org.openjdk.jmh.runner.options.Options;
9 | import org.openjdk.jmh.runner.options.OptionsBuilder;
10 |
11 | import java.nio.charset.Charset;
12 |
13 | /**
14 | * @author wayne
15 | * @version StateUsage, 2020/3/13 11:16 下午
16 | */
17 | @State(Scope.Benchmark)
18 | public class StateUsage {
19 |
20 | @Param({ "100", "200", "300", "500", "1000" })
21 | public int iterations;
22 |
23 | public Hasher murmur3;
24 |
25 | public String password = "123456";
26 |
27 | @Setup(Level.Invocation)
28 | public void setUp() {
29 | murmur3 = Hashing.murmur3_128().newHasher();
30 | }
31 |
32 | // @Fork(value = 1, warmups = 1)
33 | @Benchmark
34 | @BenchmarkMode(Mode.Throughput)
35 | public void benchMurmur3_128(StateUsage plan) {
36 |
37 | for (int i = plan.iterations; i > 0; i--) {
38 | plan.murmur3.putString(plan.password, Charset.defaultCharset());
39 | }
40 |
41 | plan.murmur3.hash();
42 | }
43 |
44 | public static void main(String[] args) throws RunnerException {
45 | Options opt = new OptionsBuilder()
46 | .include(StateUsage.class.getSimpleName())
47 | // .include(BenchMarkUsage.class.getSimpleName()+".*measureAll*")
48 | // 预热5轮
49 | .warmupIterations(3)
50 | // 度量10轮
51 | .measurementIterations(5)
52 | //代表启动多个单独的进程分别测试每个方法,我们这里指定为每个方法启动一个进程
53 | .forks(1)
54 | .build();
55 |
56 | new Runner(opt).run();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/concurrent-overview/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | concurrent-overview
13 |
14 |
15 |
--------------------------------------------------------------------------------
/concurrent-overview/src/main/java/com/flydean/CyclicBarrierUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.util.concurrent.BrokenBarrierException;
6 | import java.util.concurrent.CyclicBarrier;
7 |
8 | /**
9 | * @author wayne
10 | * @version CyclicBarrierUsage, 2020/2/24 11:32 下午
11 | */
12 | @Slf4j
13 | public class CyclicBarrierUsage implements Runnable{
14 |
15 | private CyclicBarrier barrier;
16 |
17 | public CyclicBarrierUsage(CyclicBarrier barrier) {
18 | this.barrier = barrier;
19 | }
20 |
21 | @Override
22 | public void run() {
23 | try {
24 | log.info(Thread.currentThread().getName() +
25 | " is waiting");
26 | barrier.await();
27 | log.info(Thread.currentThread().getName() +
28 | " is released");
29 | } catch (InterruptedException | BrokenBarrierException e) {
30 | e.printStackTrace();
31 | }
32 | }
33 |
34 | public void start() {
35 |
36 | CyclicBarrier cyclicBarrier = new CyclicBarrier(3, () -> {
37 | // ...
38 | log.info("All previous tasks are completed");
39 | });
40 |
41 | Thread t1 = new Thread(new CyclicBarrierUsage(cyclicBarrier), "T1");
42 | Thread t2 = new Thread(new CyclicBarrierUsage(cyclicBarrier), "T2");
43 | Thread t3 = new Thread(new CyclicBarrierUsage(cyclicBarrier), "T3");
44 |
45 | if (!cyclicBarrier.isBroken()) {
46 | t1.start();
47 | t2.start();
48 | t3.start();
49 | }
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/concurrent-overview/src/main/java/com/flydean/ExecutorServiceUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.util.concurrent.ExecutorService;
6 | import java.util.concurrent.Executors;
7 | import java.util.concurrent.TimeUnit;
8 |
9 | /**
10 | * @author wayne
11 | * @version ExecutorServiceUsage, 2020/2/24 10:07 下午
12 | */
13 | @Slf4j
14 | public class ExecutorServiceUsage {
15 | public static void main(String[] args) {
16 | ExecutorService executor = Executors.newFixedThreadPool(10);
17 | // ExecutorService executor =Executors.newSingleThreadExecutor();
18 | executor.submit(new Task());
19 | // executor.submit(() -> {
20 | // new Task();
21 | // });
22 |
23 | executor.shutdown();
24 | // executor.shutdownNow();
25 | try {
26 | executor.awaitTermination( 5l, TimeUnit.SECONDS );
27 | } catch (InterruptedException e) {
28 | e.printStackTrace();
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/concurrent-overview/src/main/java/com/flydean/FutureUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.concurrent.*;
4 |
5 | /**
6 | * @author wayne
7 | * @version FutureUsage, 2020/2/24 11:28 下午
8 | */
9 | public class FutureUsage {
10 |
11 | public static void main(String[] args) {
12 | ExecutorService executorService = Executors.newFixedThreadPool(10);
13 |
14 | Future future = executorService.submit(() -> {
15 | // ...
16 | Thread.sleep(10000l);
17 | return "Hello world";
18 | });
19 |
20 | if (future.isDone() && !future.isCancelled()) {
21 | try {
22 | String str = future.get();
23 | } catch (InterruptedException | ExecutionException e) {
24 | e.printStackTrace();
25 | }
26 | }
27 |
28 | try {
29 | future.get(10, TimeUnit.SECONDS);
30 | } catch (InterruptedException | ExecutionException | TimeoutException e) {
31 | e.printStackTrace();
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/concurrent-overview/src/main/java/com/flydean/Invoker.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.util.concurrent.Executor;
6 |
7 | /**
8 | * @author wayne
9 | * @version Invoker, 2020/2/24 9:12 下午
10 | */
11 | @Slf4j
12 | public class Invoker implements Executor {
13 |
14 | public void execute(Runnable r) {
15 | r.run();
16 | }
17 |
18 | public void execute() {
19 | Executor executor = new Invoker();
20 | executor.execute( () -> {
21 | log.info("{}", Thread.currentThread().toString());
22 | });
23 | }
24 |
25 | public static void main(String[] args) {
26 | log.info("{}",Thread.currentThread().toString());
27 |
28 | Invoker invoker=new Invoker();
29 | invoker.execute();
30 | }
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/concurrent-overview/src/main/java/com/flydean/ScheduledExecutorServiceUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.concurrent.*;
4 |
5 | /**
6 | * @author wayne
7 | * @version ScheduledExecutorServiceUsage, 2020/2/24 11:15 下午
8 | */
9 | public class ScheduledExecutorServiceUsage {
10 |
11 | public static void main(String[] args) {
12 | ScheduledExecutorService executorService
13 | = Executors.newSingleThreadScheduledExecutor();
14 |
15 | Future future = executorService.schedule(() -> {
16 | // ...
17 | return "Hello world";
18 | }, 1, TimeUnit.SECONDS);
19 |
20 | ScheduledFuture> scheduledFuture = executorService.schedule(() -> {
21 | // ...
22 | }, 1, TimeUnit.SECONDS);
23 |
24 | executorService.scheduleAtFixedRate(() -> {
25 | // ...
26 | }, 1, 10, TimeUnit.SECONDS);
27 |
28 | executorService.scheduleWithFixedDelay(() -> {
29 | // ...
30 | }, 1, 10, TimeUnit.SECONDS);
31 |
32 | executorService.shutdown();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/concurrent-overview/src/main/java/com/flydean/SemaphoreUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.util.concurrent.Semaphore;
6 |
7 | /**
8 | * @author wayne
9 | * @version SemaphoreUsage, 2020/2/24 11:41 下午
10 | */
11 | @Slf4j
12 | public class SemaphoreUsage {
13 |
14 | static Semaphore semaphore = new Semaphore(10);
15 |
16 | public void execute() throws InterruptedException {
17 |
18 | log.info("Number of threads waiting to acquire: " +
19 | semaphore.getQueueLength());
20 |
21 | if (semaphore.tryAcquire()) {
22 | try {
23 | // ...
24 | }
25 | finally {
26 | semaphore.release();
27 | }
28 | }
29 |
30 | }
31 |
32 | public static void main(String[] args) {
33 |
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/concurrent-overview/src/main/java/com/flydean/Task.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | /**
6 | * @author wayne
7 | * @version Task, 2020/2/24 10:11 下午
8 | */
9 | @Slf4j
10 | public class Task implements Runnable {
11 | @Override
12 | public void run() {
13 | // task details
14 | log.info(Thread.currentThread().getName()+"run task");
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/concurrent-overview/src/main/java/com/flydean/ThreadFactoryUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.util.concurrent.ThreadFactory;
6 |
7 | /**
8 | * @author wayne
9 | * @version ThreadFactoryUsage, 2020/2/24 11:44 下午
10 | */
11 | @Slf4j
12 | public class ThreadFactoryUsage implements ThreadFactory {
13 | private int threadId;
14 | private String name;
15 |
16 | public ThreadFactoryUsage(String name) {
17 | threadId = 1;
18 | this.name = name;
19 | }
20 |
21 | @Override
22 | public Thread newThread(Runnable r) {
23 | Thread t = new Thread(r, name + "-Thread_" + threadId);
24 | log.info("created new thread with id : " + threadId +
25 | " and name : " + t.getName());
26 | threadId++;
27 | return t;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/forkjoin/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | forkjoin
13 |
14 |
15 |
--------------------------------------------------------------------------------
/forkjoin/src/main/java/com.flydean/CustomRecursiveAction.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.concurrent.ForkJoinTask;
6 | import java.util.concurrent.RecursiveAction;
7 | import java.util.logging.Logger;
8 |
9 | /**
10 | * @author wayne
11 | * @version CustomRecursiveAction, 2020/3/7 2:17 下午
12 | */
13 | public class CustomRecursiveAction extends RecursiveAction {
14 |
15 | private String workload = "";
16 | private static final int THRESHOLD = 4;
17 |
18 | private static Logger logger =
19 | Logger.getAnonymousLogger();
20 |
21 | public CustomRecursiveAction(String workload) {
22 | this.workload = workload;
23 | }
24 |
25 | @Override
26 | protected void compute() {
27 | if (workload.length() > THRESHOLD) {
28 | ForkJoinTask.invokeAll(createSubtasks());
29 | } else {
30 | processing(workload);
31 | }
32 | }
33 |
34 | private List createSubtasks() {
35 | List subtasks = new ArrayList<>();
36 |
37 | String partOne = workload.substring(0, workload.length() / 2);
38 | String partTwo = workload.substring(workload.length() / 2, workload.length());
39 |
40 | subtasks.add(new CustomRecursiveAction(partOne));
41 | subtasks.add(new CustomRecursiveAction(partTwo));
42 |
43 | return subtasks;
44 | }
45 |
46 | private void processing(String work) {
47 | String result = work.toUpperCase();
48 | logger.info("This result - (" + result + ") - was processed by "
49 | + Thread.currentThread().getName());
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/forkjoin/src/main/java/com.flydean/CustomRecursiveTask.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.Collection;
6 | import java.util.List;
7 | import java.util.concurrent.ForkJoinTask;
8 | import java.util.concurrent.RecursiveTask;
9 |
10 | /**
11 | * @author wayne
12 | * @version CustomRecursiveTask, 2020/3/7 2:18 下午
13 | */
14 | public class CustomRecursiveTask extends RecursiveTask {
15 | private int[] arr;
16 |
17 | private static final int THRESHOLD = 20;
18 |
19 | public CustomRecursiveTask(int[] arr) {
20 | this.arr = arr;
21 | }
22 |
23 | @Override
24 | protected Integer compute() {
25 | if (arr.length > THRESHOLD) {
26 | return ForkJoinTask.invokeAll(createSubtasks())
27 | .stream()
28 | .mapToInt(ForkJoinTask::join)
29 | .sum();
30 | } else {
31 | return processing(arr);
32 | }
33 | }
34 |
35 | private Collection createSubtasks() {
36 | List dividedTasks = new ArrayList<>();
37 | dividedTasks.add(new CustomRecursiveTask(
38 | Arrays.copyOfRange(arr, 0, arr.length / 2)));
39 | dividedTasks.add(new CustomRecursiveTask(
40 | Arrays.copyOfRange(arr, arr.length / 2, arr.length)));
41 | return dividedTasks;
42 | }
43 |
44 | private Integer processing(int[] arr) {
45 | return Arrays.stream(arr)
46 | .filter(a -> a > 10 && a < 27)
47 | .map(a -> a * 10)
48 | .sum();
49 | }
50 | }
--------------------------------------------------------------------------------
/forkjoin/src/main/java/com.flydean/ForkJoinUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.ArrayList;
4 | import java.util.concurrent.ForkJoinPool;
5 |
6 | /**
7 | * @author wayne
8 | * @version ForkJoinUsage, 2020/3/7 2:08 下午
9 | */
10 | public class ForkJoinUsage {
11 |
12 | public static void main(String[] args) {
13 | ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
14 |
15 | // ForkJoinPool forkJoinPool = new ForkJoinPool(2);
16 |
17 | CustomRecursiveAction customRecursiveAction= new CustomRecursiveAction("fork join action test!!!");
18 | int[] intArray= {12,12,13,14,15};
19 | CustomRecursiveTask customRecursiveTask= new CustomRecursiveTask(intArray);
20 |
21 | int result = forkJoinPool.invoke(customRecursiveTask);
22 | System.out.println(result);
23 |
24 | customRecursiveTask.fork();
25 | int result2= customRecursiveTask.join();
26 | System.out.println(result2);
27 |
28 | forkJoinPool.invoke(customRecursiveAction);
29 |
30 | customRecursiveAction.fork();
31 | customRecursiveAction.invoke();
32 |
33 |
34 |
35 |
36 |
37 |
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/future/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | feature
13 |
14 |
15 |
--------------------------------------------------------------------------------
/future/src/main/java/com/flydean/FutureUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.concurrent.*;
4 |
5 | /**
6 | * @author wayne
7 | * @version FutureUsage, 2020/3/1 10:22 下午
8 | */
9 | public class FutureUsage {
10 |
11 | private ExecutorService executor
12 | = Executors.newSingleThreadExecutor();
13 |
14 | public Future calculate(Integer input) {
15 | return executor.submit(() -> {
16 | System.out.println("Calculating..."+ input);
17 | Thread.sleep(1000);
18 | return input * input;
19 | });
20 | }
21 |
22 | public void shutDown(){
23 | executor.shutdown();
24 | }
25 |
26 | public static void main(String[] args) throws ExecutionException, InterruptedException {
27 |
28 | FutureUsage futureUsage=new FutureUsage();
29 | Future futureOne = futureUsage.calculate(20);
30 | while(!futureOne.isDone()) {
31 | System.out.println("Calculating...");
32 | Thread.sleep(300);
33 | }
34 | Integer result = futureOne.get();
35 | // Integer result = futureOne.get(500, TimeUnit.MILLISECONDS);
36 |
37 | Future futureTwo = futureUsage.calculate(4);
38 |
39 | boolean canceled = futureTwo.cancel(true);
40 |
41 |
42 | Future future1 = futureUsage.calculate(10);
43 | Future future2 = futureUsage.calculate(100);
44 |
45 | while (!(future1.isDone() && future2.isDone())) {
46 | System.out.println(
47 | String.format(
48 | "future1 is %s and future2 is %s",
49 | future1.isDone() ? "done" : "not done",
50 | future2.isDone() ? "done" : "not done"
51 | )
52 | );
53 | Thread.sleep(300);
54 | }
55 |
56 | Integer result1 = future1.get();
57 | Integer result2 = future2.get();
58 |
59 | System.out.println(result1 + " and " + result2);
60 |
61 | futureUsage.shutDown();
62 |
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/futureTask/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | futureTask
13 |
14 |
15 | junit
16 | junit
17 | 4.12
18 | compile
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/futureTask/src/main/java/com.flydean/FutureTaskUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.junit.Test;
5 |
6 | import java.util.concurrent.*;
7 |
8 | /**
9 | * @author wayne
10 | * @version FutureTaskUsage, 2020/3/15 9:14 下午
11 | */
12 | @Slf4j
13 | public class FutureTaskUsage {
14 |
15 | @Test
16 | public void convertRunnableToCallable() throws ExecutionException, InterruptedException {
17 | FutureTask futureTask = new FutureTask<>(new Callable() {
18 | @Override
19 | public Integer call() throws Exception {
20 | log.info("inside callable future task ...");
21 | return 0;
22 | }
23 | });
24 |
25 | Thread thread= new Thread(futureTask);
26 | thread.start();
27 | log.info(futureTask.get().toString());
28 | }
29 |
30 | @Test
31 | public void workWithExecutorService() throws ExecutionException, InterruptedException {
32 | FutureTask futureTask = new FutureTask<>(new Callable() {
33 | @Override
34 | public Integer call() throws Exception {
35 | log.info("inside futureTask");
36 | return 1;
37 | }
38 | });
39 | ExecutorService executor = Executors.newCachedThreadPool();
40 | executor.submit(futureTask);
41 | executor.shutdown();
42 | log.info(futureTask.get().toString());
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/interrupt/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | interrupt
13 |
14 |
15 | junit
16 | junit
17 | 4.13.1
18 | compile
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/interrupt/src/main/java/com/flydean/InterruptThread.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.junit.Test;
5 |
6 | /**
7 | * @author wayne
8 | * @version InterruptThread, 2020/3/4 11:46 上午
9 | */
10 | @Slf4j
11 | public class InterruptThread extends Thread {
12 | @Override
13 | public void run() {
14 | for (int i = 0; i < 1000; i++) {
15 | log.info("i= {}", (i+1));
16 | log.info("call inside thread.interrupted(): {}", Thread.interrupted());
17 | }
18 | }
19 |
20 | @Test
21 | public void testInterrupt(){
22 | InterruptThread thread=new InterruptThread();
23 | thread.start();
24 | thread.interrupt();
25 | //test isInterrupted
26 | log.info("first call isInterrupted(): {}", thread.isInterrupted());
27 | log.info("second call isInterrupted(): {}", thread.isInterrupted());
28 |
29 | //test interrupted()
30 | log.info("first call outside thread.interrupted(): {}", Thread.interrupted());
31 | log.info("second call outside thread.interrupted() {}:", Thread.interrupted());
32 | log.info("thread is alive : {}",thread.isAlive() );
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/join/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | join
13 |
14 |
15 | junit
16 | junit
17 | 4.13.1
18 | compile
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/join/src/main/java/com/flydean/JoinThread.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.Data;
4 | import lombok.NoArgsConstructor;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.junit.Test;
7 |
8 | /**
9 | * @author wayne
10 | * @version JoinUsage, 2020/3/4 6:11 上午
11 | */
12 | @Slf4j
13 | @NoArgsConstructor
14 | public class JoinThread extends Thread{
15 | public int processingCount = 0;
16 |
17 | JoinThread(int processingCount) {
18 | this.processingCount = processingCount;
19 | log.info("Thread Created");
20 | }
21 |
22 | @Override
23 | public void run() {
24 | log.info("Thread " + Thread.currentThread().getName() + " started");
25 | while (processingCount > 0) {
26 | try {
27 | Thread.sleep(1000);
28 | } catch (InterruptedException e) {
29 | log.info("Thread " + Thread.currentThread().getName() + " interrupted");
30 | }
31 | processingCount--;
32 | }
33 | log.info("Thread " + Thread.currentThread().getName() + " exiting");
34 | }
35 |
36 | @Test
37 | public void joinTest()
38 | throws InterruptedException {
39 | Thread t2 = new Thread(new JoinThread(1));
40 | t2.start();
41 | log.info("Invoking join");
42 | t2.join();
43 | log.info("Returned from join");
44 | log.info("t2 status {}",t2.isAlive());
45 | }
46 |
47 | @Test
48 | public void testJoinTimeout()
49 | throws InterruptedException {
50 | Thread t3 = new Thread(new JoinThread(10));
51 | t3.start();
52 | t3.join(1000);
53 | log.info("t3 status {}", t3.isAlive());
54 | }
55 |
56 | @Test
57 | public void testHappenBefore() throws InterruptedException {
58 | JoinThread t4 = new JoinThread(10);
59 | t4.start();
60 | // not guaranteed to stop even if t4 finishes.
61 | do {
62 | log.info("inside the loop");
63 | Thread.sleep(1000);
64 | } while ( t4.processingCount > 0);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/kill-thread/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | kill-thread
13 |
14 |
15 | junit
16 | junit
17 | 4.13.1
18 | compile
19 |
20 |
21 | org.junit.jupiter
22 | junit-jupiter
23 | RELEASE
24 | compile
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/kill-thread/src/main/java/com/flydean/KillThread.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.Data;
4 | import lombok.extern.slf4j.Slf4j;
5 |
6 | import java.util.concurrent.atomic.AtomicBoolean;
7 |
8 | /**
9 | * @author wayne
10 | * @version KillThread, 2020/3/4 7:15 上午
11 | */
12 |
13 | @Data
14 | @Slf4j
15 | public class KillThread implements Runnable {
16 | private Thread worker;
17 | private final AtomicBoolean running = new AtomicBoolean(false);
18 | private int interval;
19 |
20 | public KillThread(int sleepInterval) {
21 | interval = sleepInterval;
22 | }
23 |
24 | public void start() {
25 | worker = new Thread(this);
26 | worker.start();
27 | }
28 |
29 | public void interrupt() {
30 | running.set(false);
31 | worker.interrupt();
32 | }
33 |
34 | public void stop() {
35 | running.set(false);
36 | }
37 |
38 | public void run() {
39 | running.set(true);
40 | while (running.get()) {
41 | try {
42 | Thread.sleep(interval);
43 | } catch (InterruptedException e){
44 | log.info("isInterrupted status {}", Thread.currentThread().isInterrupted());
45 | Thread.currentThread().interrupt();
46 | log.info("Thread was interrupted, Failed to complete operation");
47 | }
48 | // do something here
49 | }
50 | log.info("finished");
51 | }
52 |
53 | public static void main(String[] args) {
54 | KillThread killThread= new KillThread(1000);
55 | killThread.start();
56 | // killThread.stop();
57 | killThread.interrupt();
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/nonblock/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | nonblock
13 |
14 |
15 |
--------------------------------------------------------------------------------
/nonblock/src/main/java/com.flydean/ConcurrentStack.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.concurrent.atomic.AtomicReference;
4 |
5 | /**
6 | * @author wayne
7 | * @version ConcurrentStack, 2020/3/28 8:04 下午
8 | */
9 | public class ConcurrentStack {
10 |
11 | AtomicReference> top= new AtomicReference<>();
12 |
13 | public void push(E item){
14 | Node newNode= new Node<>(item);
15 | Node oldNode;
16 | do{
17 | oldNode=top.get();
18 | newNode.next= oldNode;
19 | }while(!top.compareAndSet(oldNode, newNode));
20 | }
21 |
22 | public E pop(){
23 | Node oldNode;
24 | Node newNode;
25 | do {
26 | oldNode = top.get();
27 | if(oldNode == null){
28 | return null;
29 | }
30 | newNode=oldNode.next;
31 | }while(!top.compareAndSet(oldNode, newNode));
32 | return oldNode.item;
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/nonblock/src/main/java/com.flydean/LinkedNode.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.concurrent.atomic.AtomicReference;
4 |
5 | /**
6 | * @author wayne
7 | * @version LinkedNode, 2020/3/28 8:27 下午
8 | */
9 | public class LinkedNode {
10 | public final E item;
11 | public final AtomicReference> next;
12 |
13 | public LinkedNode(E item, LinkedNode next){
14 | this.item=item;
15 | this.next=new AtomicReference<>(next);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/nonblock/src/main/java/com.flydean/LinkedQueue.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.concurrent.atomic.AtomicReference;
4 |
5 | /**
6 | * @author wayne
7 | * @version LinkedQueue, 2020/3/28 8:29 下午
8 | */
9 | public class LinkedQueue {
10 | private final LinkedNode nullNode= new LinkedNode<>(null, null);
11 | private final AtomicReference> head= new AtomicReference<>(nullNode);
12 | private final AtomicReference> tail= new AtomicReference<>(nullNode);
13 |
14 | public boolean put(E item){
15 | LinkedNode newNode = new LinkedNode<>(item, null);
16 | while (true){
17 | LinkedNode currentTail= tail.get();
18 | LinkedNode tailNext= currentTail.next.get();
19 | if(currentTail == tail.get()){
20 | if (tailNext != null) {
21 | //有其他的线程已经插入了一个节点,但是还没有将tail指向最新的节点
22 | tail.compareAndSet(currentTail, tailNext);
23 | }else{
24 | //没有其他的线程插入节点,那么做两件事情:1. 插入新节点,2.将tail指向最新的节点
25 | if(currentTail.next.compareAndSet(null, newNode)){
26 | tail.compareAndSet(currentTail, newNode);
27 | }
28 | }
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/nonblock/src/main/java/com.flydean/Node.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version Node, 2020/3/28 7:52 下午
6 | */
7 | public class Node {
8 | public final E item;
9 | public Node next;
10 |
11 | public Node(E item){
12 | this.item=item;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.example
8 | learn-java-concurrency
9 | pom
10 | 1.0-SNAPSHOT
11 |
12 |
13 | 1.8
14 | 1.8
15 |
16 |
17 |
18 |
19 | concurrent-overview
20 | Synchronized
21 | volatile
22 | wait-sleep
23 | future
24 | ExecutorService
25 | runnable-callable
26 | ThreadLocal
27 | thread-lifecycle
28 | join
29 | kill-thread
30 | atomic
31 | interrupt
32 | DaemonThread
33 | threadPool
34 | forkjoin
35 | Locks
36 | CountDownLatch
37 | CyclicBarrier
38 | benchmark
39 | ThreadLocalRandom
40 | futureTask
41 | CompletableFuture
42 | Phaser
43 | Semaphore
44 | MemoizedCalculate
45 | CompletionService
46 | ExecutorServiceShutdown
47 | ThreadPoolDeadlock
48 | rejectPolicy
49 | accountTransferLock
50 | AQS
51 | CAS
52 | nonblock
53 | reorder
54 | Exchanger
55 | RCU
56 |
57 |
58 |
59 |
60 | org.projectlombok
61 | lombok
62 | 1.18.12
63 |
64 |
65 |
66 | ch.qos.logback
67 | logback-classic
68 | 1.2.3
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/rejectPolicy/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | rejectPolicy
13 |
14 |
15 |
--------------------------------------------------------------------------------
/rejectPolicy/src/main/java/com/flydean/RejectPolicyUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.concurrent.BlockingQueue;
4 | import java.util.concurrent.LinkedBlockingDeque;
5 | import java.util.concurrent.ThreadPoolExecutor;
6 | import java.util.concurrent.TimeUnit;
7 |
8 | /**
9 | * @author wayne
10 | * @version RejectPolicyUsage, 2020/3/26 11:01 上午
11 | */
12 | public class RejectPolicyUsage {
13 |
14 | public static void main(String[] args) {
15 | ThreadPoolExecutor threadPoolExecutor= new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, new LinkedBlockingDeque(20));
16 | threadPoolExecutor.setRejectedExecutionHandler(
17 | new ThreadPoolExecutor.AbortPolicy()
18 | );
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/rejectPolicy/src/main/java/com/flydean/SemaphoreUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.concurrent.Executor;
4 | import java.util.concurrent.RejectedExecutionException;
5 | import java.util.concurrent.Semaphore;
6 |
7 | /**
8 | * @author wayne
9 | * @version SemaphoreUsage, 2020/3/26 11:19 上午
10 | */
11 | public class SemaphoreUsage {
12 |
13 | private final Executor executor;
14 | private final Semaphore semaphore;
15 |
16 | public SemaphoreUsage(Executor executor, int count) {
17 | this.executor = executor;
18 | this.semaphore = new Semaphore(count);
19 | }
20 |
21 | public void submitTask(final Runnable command) throws InterruptedException {
22 | semaphore.acquire();
23 | try {
24 | executor.execute(() -> {
25 | try {
26 | command.run();
27 | } finally {
28 | semaphore.release();
29 | }
30 | }
31 | );
32 | } catch (RejectedExecutionException e) {
33 | semaphore.release();
34 | }
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/reorder/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | reorder
13 |
14 |
15 |
--------------------------------------------------------------------------------
/reorder/src/main/java/com.flydean/Book.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version ResouceFactory, 2020/3/29 7:17 下午
6 | */
7 | public class Book {
8 |
9 | private static Book book;
10 |
11 | public static Book getBook(){
12 | if(book==null){
13 | book = new Book();
14 | }
15 | return book;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/reorder/src/main/java/com.flydean/BookDLC.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version BookDLC, 2020/3/29 8:58 下午
6 | */
7 | public class BookDLC {
8 | private volatile static BookDLC bookDLC;
9 |
10 | public static BookDLC getBookDLC(){
11 | if(bookDLC == null ){
12 | synchronized (BookDLC.class){
13 | if(bookDLC ==null){
14 | bookDLC=new BookDLC();
15 | }
16 | }
17 | }
18 | return bookDLC;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/reorder/src/main/java/com.flydean/BookStatic.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version BookStatic, 2020/3/29 7:51 下午
6 | */
7 | public class BookStatic {
8 | private static BookStatic bookStatic= new BookStatic();
9 |
10 | public static BookStatic getBookStatic(){
11 | return bookStatic;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/reorder/src/main/java/com.flydean/BookStaticLazy.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version BookStatic, 2020/3/29 7:51 下午
6 | */
7 | public class BookStaticLazy {
8 |
9 | private static class BookStaticHolder{
10 | private static BookStaticLazy bookStatic= new BookStaticLazy();
11 | }
12 |
13 | public static BookStaticLazy getBookStatic(){
14 | return BookStaticHolder.bookStatic;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/reorder/src/main/java/com.flydean/FinalSafe.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.HashMap;
4 |
5 | /**
6 | * @author wayne
7 | * @version FinalSafe, 2020/3/29 9:21 下午
8 | */
9 | public class FinalSafe {
10 | private final HashMap hashMap;
11 |
12 | public FinalSafe(){
13 | hashMap= new HashMap<>();
14 | hashMap.put("key1","value1");
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/reorder/src/main/java/com.flydean/Reorder.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | /**
6 | * @author wayne
7 | * @version Reorder, 2020/3/29 11:24 上午
8 | */
9 | @Slf4j
10 | public class Reorder {
11 |
12 | int x=0, y=0;
13 | int a=0, b=0;
14 |
15 | private void reorderMethod() throws InterruptedException {
16 |
17 | Thread one = new Thread(()->{
18 | a=1;
19 | x=b;
20 | });
21 |
22 | Thread two = new Thread(()->{
23 | b=1;
24 | y=a;
25 | });
26 | one.start();
27 | two.start();
28 | one.join();
29 | two.join();
30 | log.info("{},{}", x, y);
31 | }
32 |
33 | public static void main(String[] args) throws InterruptedException {
34 |
35 | for (int i=0; i< 100; i++){
36 | new Reorder().reorderMethod();
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/runnable-callable/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | runnable-callable
13 |
14 |
15 |
--------------------------------------------------------------------------------
/runnable-callable/src/main/java/com/flydean/CallableUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.util.concurrent.ExecutionException;
6 | import java.util.concurrent.ExecutorService;
7 | import java.util.concurrent.Executors;
8 | import java.util.concurrent.Future;
9 |
10 | /**
11 | * @author wayne
12 | * @version CallableUsage, 2020/3/2 8:13 上午
13 | */
14 | @Slf4j
15 | public class CallableUsage {
16 |
17 | public void executeTask() {
18 | ExecutorService executorService = Executors.newSingleThreadExecutor();
19 | Future future = executorService.submit(()->{
20 | log.info("in callable!!!!");
21 | return "callable";
22 | });
23 | executorService.shutdown();
24 | }
25 |
26 | public void executeTaskWithException(){
27 | ExecutorService executorService = Executors.newSingleThreadExecutor();
28 | Future future = executorService.submit(()->{
29 | log.info("in callable!!!!");
30 | throw new CustomerException("a customer Exception");
31 | });
32 | try {
33 | Object object= future.get();
34 | } catch (InterruptedException e) {
35 | e.printStackTrace();
36 | } catch (ExecutionException e) {
37 | e.printStackTrace();
38 | e.getCause();
39 | }
40 | executorService.shutdown();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/runnable-callable/src/main/java/com/flydean/CustomerException.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version CustomerException, 2020/3/2 9:17 上午
6 | */
7 | public class CustomerException extends Exception {
8 | public CustomerException(String name) {
9 | super(name);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/runnable-callable/src/main/java/com/flydean/RunnableUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.util.concurrent.ExecutorService;
6 | import java.util.concurrent.Executors;
7 | import java.util.concurrent.Future;
8 |
9 | /**
10 | * @author wayne
11 | * @version RunnableUsage, 2020/3/2 8:13 上午
12 | */
13 | @Slf4j
14 | public class RunnableUsage {
15 |
16 | public void executeTask() {
17 | ExecutorService executorService = Executors.newSingleThreadExecutor();
18 | Future future = executorService.submit(()->log.info("in runnable!!!!"));
19 | executorService.shutdown();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/thread-lifecycle/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | thread-lifecycle
13 |
14 |
15 |
--------------------------------------------------------------------------------
/thread-lifecycle/src/main/java/com/flydean/BlockThread.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | /**
6 | * @author wayne
7 | * @version BlockThread, 2020/3/3 10:22 上午
8 | */
9 | @Slf4j
10 | public class BlockThread implements Runnable {
11 | @Override
12 | public void run() {
13 | loopResource();
14 | }
15 |
16 | public static synchronized void loopResource() {
17 | while(true) {
18 | //无限循环
19 | }
20 | }
21 |
22 | public static void main(String[] args) throws InterruptedException {
23 | Thread t1 = new Thread(new BlockThread());
24 | Thread t2 = new Thread(new BlockThread());
25 |
26 | t1.start();
27 | t2.start();
28 |
29 | Thread.sleep(1000);
30 | log.info(t1.getState().toString());
31 | log.info(t2.getState().toString());
32 | System.exit(0);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/thread-lifecycle/src/main/java/com/flydean/NewThread.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | /**
6 | * @author wayne
7 | * @version NewThread, 2020/3/3 10:14 上午
8 | */
9 | @Slf4j
10 | public class NewThread implements Runnable{
11 | public static void main(String[] args) {
12 | Runnable runnable = new NewThread();
13 | Thread t = new Thread(runnable);
14 | log.info(t.getState().toString());
15 | }
16 |
17 | @Override
18 | public void run() {
19 |
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/thread-lifecycle/src/main/java/com/flydean/RunnableThread.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | /**
6 | * @author wayne
7 | * @version RunnableThread, 2020/3/3 10:17 上午
8 | */
9 | @Slf4j
10 | public class RunnableThread implements Runnable {
11 | @Override
12 | public void run() {
13 |
14 | }
15 |
16 | public static void main(String[] args) {
17 | Runnable runnable = new RunnableThread();
18 | Thread t = new Thread(runnable);
19 | t.start();
20 | log.info(t.getState().toString());
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/thread-lifecycle/src/main/java/com/flydean/TerminatedThread.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | /**
6 | * @author wayne
7 | * @version TerminatedThread, 2020/3/3 10:55 上午
8 | */
9 | @Slf4j
10 | public class TerminatedThread implements Runnable{
11 | @Override
12 | public void run() {
13 |
14 | }
15 |
16 | public static void main(String[] args) throws InterruptedException {
17 | Thread t1 = new Thread(new TerminatedThread());
18 | t1.start();
19 | // The following sleep method will give enough time for
20 | // thread t1 to complete
21 | Thread.sleep(1000);
22 | log.info(t1.getState().toString());
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/thread-lifecycle/src/main/java/com/flydean/TimedWaitThread.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | /**
6 | * @author wayne
7 | * @version TimedWaitThread, 2020/3/3 10:42 上午
8 | */
9 | @Slf4j
10 | public class TimedWaitThread implements Runnable{
11 | @Override
12 | public void run() {
13 | try {
14 | Thread.sleep(5000);
15 | } catch (InterruptedException e) {
16 | Thread.currentThread().interrupt();
17 | log.error("Thread interrupted", e);
18 | }
19 | }
20 |
21 | public static void main(String[] args) throws InterruptedException {
22 | TimedWaitThread obj1 = new TimedWaitThread();
23 | Thread t1 = new Thread(obj1);
24 | t1.start();
25 |
26 | // The following sleep will give enough time for ThreadScheduler
27 | // to start processing of thread t1
28 | Thread.sleep(1000);
29 | log.info(t1.getState().toString());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/thread-lifecycle/src/main/java/com/flydean/WaitThread.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | /**
6 | * @author wayne
7 | * @version WaitThread, 2020/3/3 10:29 上午
8 | */
9 | @Slf4j
10 | public class WaitThread implements Runnable{
11 |
12 | public static Thread t1;
13 | @Override
14 | public void run() {
15 | Thread t2 = new Thread(()->{
16 | try {
17 | Thread.sleep(1000);
18 | } catch (InterruptedException e) {
19 | Thread.currentThread().interrupt();
20 | log.error("Thread interrupted", e);
21 | }
22 | log.info("t1 "+t1.getState().toString());
23 | });
24 | t2.start();
25 |
26 | try {
27 | t2.join();
28 | } catch (InterruptedException e) {
29 | Thread.currentThread().interrupt();
30 | log.error("Thread interrupted", e);
31 | }
32 | log.info("t2 "+t2.getState().toString());
33 | }
34 |
35 | public static void main(String[] args) {
36 | t1 = new Thread(new WaitThread());
37 | t1.start();
38 |
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/threadPool/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | threadPool
13 |
14 |
15 |
16 | com.google.guava
17 | guava
18 | 19.0
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/threadPool/src/main/java/com/flydean/CountingTask.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import java.util.concurrent.ForkJoinPool;
4 | import java.util.concurrent.ForkJoinTask;
5 | import java.util.concurrent.RecursiveTask;
6 |
7 | /**
8 | * @author wayne
9 | * @version CountingTask, 2020/3/6 10:59 上午
10 | */
11 | public class CountingTask extends RecursiveTask {
12 |
13 | private final TreeNode node;
14 |
15 | public CountingTask(TreeNode node) {
16 | this.node = node;
17 | }
18 |
19 | @Override
20 | protected Integer compute() {
21 | return node.value + node.children.stream()
22 | .map(childNode -> new CountingTask(childNode).fork()).mapToInt(ForkJoinTask::join).sum();
23 | }
24 |
25 | public static void main(String[] args) {
26 | TreeNode tree = new TreeNode(5,
27 | new TreeNode(3), new TreeNode(2,
28 | new TreeNode(2), new TreeNode(8)));
29 |
30 | ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
31 | int sum = forkJoinPool.invoke(new CountingTask(tree));
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/threadPool/src/main/java/com/flydean/ExecutorServiceUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.util.concurrent.Executor;
6 | import java.util.concurrent.ExecutorService;
7 | import java.util.concurrent.Executors;
8 |
9 | /**
10 | * @author wayne
11 | * @version ExecutorServiceUsage, 2020/3/6 9:50 上午
12 | */
13 | @Slf4j
14 | public class ExecutorServiceUsage {
15 |
16 | public static void main(String[] args) {
17 |
18 | Executor executor = Executors.newSingleThreadExecutor();
19 | executor.execute(() -> log.info("in Executor"));
20 |
21 |
22 | ExecutorService executorService= Executors.newCachedThreadPool();
23 | executorService.submit(()->log.info("in ExecutorService"));
24 | executorService.shutdown();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/threadPool/src/main/java/com/flydean/ScheduledThreadPoolExecutorUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.util.concurrent.*;
6 |
7 | /**
8 | * @author wayne
9 | * @version ScheduledThreadPoolExecutorUsage, 2020/3/6 10:42 上午
10 | */
11 | @Slf4j
12 | public class ScheduledThreadPoolExecutorUsage {
13 |
14 | public static void main(String[] args) throws InterruptedException {
15 | ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
16 | executor.schedule(() -> {
17 | log.info("Hello World");
18 | }, 500, TimeUnit.MILLISECONDS);
19 |
20 | CountDownLatch lock = new CountDownLatch(3);
21 |
22 | ScheduledExecutorService executor2 = Executors.newScheduledThreadPool(5);
23 | ScheduledFuture> future = executor2.scheduleAtFixedRate(() -> {
24 | log.info("in ScheduledFuture");
25 | lock.countDown();
26 | }, 500, 100, TimeUnit.MILLISECONDS);
27 |
28 | lock.await(1000, TimeUnit.MILLISECONDS);
29 | future.cancel(true);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/threadPool/src/main/java/com/flydean/ThreadPoolExecutorUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.util.concurrent.*;
6 | import java.util.concurrent.atomic.AtomicInteger;
7 |
8 | /**
9 | * @author wayne
10 | * @version ThreadPoolExecutorUsage, 2020/3/6 10:15 上午
11 | */
12 | @Slf4j
13 | public class ThreadPoolExecutorUsage {
14 |
15 | public static void main(String[] args) {
16 | ThreadPoolExecutor threadPoolExecutor =
17 | new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
18 | new LinkedBlockingQueue());
19 | threadPoolExecutor.submit(()->log.info("submit through threadPoolExecutor"));
20 | threadPoolExecutor.shutdown();
21 |
22 | ThreadPoolExecutor executor1 =
23 | (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
24 | executor1.submit(() -> {
25 | Thread.sleep(1000);
26 | return null;
27 | });
28 | executor1.submit(() -> {
29 | Thread.sleep(1000);
30 | return null;
31 | });
32 | executor1.submit(() -> {
33 | Thread.sleep(1000);
34 | return null;
35 | });
36 | log.info("executor1 poolsize {}",executor1.getPoolSize());
37 | log.info("executor1 queuesize {}", executor1.getQueue().size());
38 | executor1.shutdown();
39 |
40 | ThreadPoolExecutor executor2 =
41 | (ThreadPoolExecutor) Executors.newCachedThreadPool();
42 | executor2.submit(() -> {
43 | Thread.sleep(1000);
44 | return null;
45 | });
46 | executor2.submit(() -> {
47 | Thread.sleep(1000);
48 | return null;
49 | });
50 | executor2.submit(() -> {
51 | Thread.sleep(1000);
52 | return null;
53 | });
54 |
55 | log.info("executor2 poolsize {}", executor2.getPoolSize());
56 | log.info("executor2 queue size {}", executor2.getQueue().size());
57 | executor2.shutdown();
58 |
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/threadPool/src/main/java/com/flydean/TreeNode.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import com.google.common.collect.Sets;
4 |
5 | import java.util.Set;
6 |
7 | /**
8 | * @author wayne
9 | * @version TreeNode, 2020/3/6 10:58 上午
10 | */
11 |
12 | public class TreeNode {
13 |
14 | int value;
15 |
16 | Set children;
17 |
18 | TreeNode(int value, TreeNode... children) {
19 | this.value = value;
20 | this.children = Sets.newHashSet(children);
21 | }
22 | }
--------------------------------------------------------------------------------
/volatile/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | volatile
13 |
14 |
15 | junit
16 | junit
17 | 4.13.1
18 | test
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/volatile/src/main/java/com/flydean/VolatileFalseUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version VolatileUsage, 2020/2/28 8:30 上午
6 | */
7 | public class VolatileFalseUsage {
8 | private volatile int count = 0;
9 |
10 | public void incrementCount() {
11 | count++;
12 | }
13 | public int getCount() {
14 | return count;
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/volatile/src/main/java/com/flydean/VolatileHappenBeforeUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version VolatileHappenBeforeUsage, 2020/2/28 9:34 上午
6 | */
7 | public class VolatileHappenBeforeUsage {
8 |
9 | int a = 0;
10 | volatile boolean flag = false;
11 |
12 | public void writer() {
13 | a = 1; // 1 线程A修改共享变量
14 | flag = true; // 2 线程A写volatile变量
15 | }
16 |
17 | public void reader() {
18 | if (flag) { // 3 线程B读同一个volatile变量
19 | int i = a; // 4 线程B读共享变量
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/volatile/src/main/java/com/flydean/VolatileTrueUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version VolatileTrueUsage, 2020/2/28 9:11 上午
6 | */
7 | public class VolatileTrueUsage {
8 | private volatile int count = 0;
9 |
10 | public void setCount(int number) {
11 | count=number;
12 | }
13 | public int getCount() {
14 | return count;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/volatile/src/main/java/com/flydean/VolatileWithoutUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | /**
4 | * @author wayne
5 | * @version VolatileUsage, 2020/2/28 8:30 上午
6 | */
7 | public class VolatileWithoutUsage {
8 | private int count = 0;
9 |
10 | public void incrementCount() {
11 | count++;
12 | }
13 | public int getCount() {
14 | return count;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/volatile/src/test/java/com/flydean/VolatileUsageTest.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import org.junit.Test;
4 |
5 | import java.util.concurrent.ExecutorService;
6 | import java.util.concurrent.Executors;
7 | import java.util.concurrent.TimeUnit;
8 | import java.util.stream.IntStream;
9 |
10 | import static org.junit.Assert.assertEquals;
11 |
12 | /**
13 | * @author wayne
14 | * @version VolatileUsageTest, 2020/2/28 8:31 上午
15 | */
16 | public class VolatileUsageTest {
17 |
18 | @Test
19 | public void testWithoutVolatile() throws InterruptedException {
20 | ExecutorService service= Executors.newFixedThreadPool(3);
21 | VolatileWithoutUsage volatileWithoutUsage=new VolatileWithoutUsage();
22 |
23 | IntStream.range(0,1000).forEach(count ->service.submit(volatileWithoutUsage::incrementCount) );
24 | service.shutdown();
25 | service.awaitTermination(1000, TimeUnit.MILLISECONDS);
26 | assertEquals(1000,volatileWithoutUsage.getCount() );
27 | }
28 |
29 | @Test
30 | public void testWithVolatileFalseUsage() throws InterruptedException {
31 | ExecutorService service= Executors.newFixedThreadPool(3);
32 | VolatileFalseUsage volatileFalseUsage=new VolatileFalseUsage();
33 |
34 | IntStream.range(0,1000).forEach(count ->service.submit(volatileFalseUsage::incrementCount) );
35 | service.shutdown();
36 | service.awaitTermination(5000, TimeUnit.MILLISECONDS);
37 | assertEquals(1000,volatileFalseUsage.getCount() );
38 | }
39 |
40 | @Test
41 | public void testWithVolatileTrueUsage() throws InterruptedException {
42 | VolatileTrueUsage volatileTrueUsage=new VolatileTrueUsage();
43 | Thread threadA = new Thread(()->volatileTrueUsage.setCount(10));
44 | threadA.start();
45 | Thread.sleep(100);
46 |
47 | Thread reader = new Thread(() -> {
48 | int valueReadByThread = volatileTrueUsage.getCount();
49 | assertEquals(10, valueReadByThread);
50 | });
51 | reader.start();
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/wait-sleep/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | learn-java-concurrency
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | wait-sleep
13 |
14 |
15 | junit
16 | junit
17 | 4.13.1
18 | test
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/wait-sleep/src/main/java/com/flydean/SleepUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | /**
6 | * @author wayne
7 | * @version SleepUsage, 2020/2/29 10:26 上午
8 | */
9 | @Slf4j
10 | public class SleepUsage {
11 |
12 | public static void sleepExample() throws InterruptedException {
13 | Thread.sleep(1000);
14 | Thread.currentThread().interrupt();
15 | log.info(
16 | "Thread '" + Thread.currentThread().getName() +
17 | "' is woken after sleeping for 1 second");
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/wait-sleep/src/main/java/com/flydean/WaitNotifyUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | /**
6 | * @author wayne
7 | * @version WaitNotifyUsage, 2020/2/29 9:19 上午
8 | */
9 | @Slf4j
10 | public class WaitNotifyUsage {
11 |
12 | private int count =0;
13 |
14 | public void produceMessage() throws InterruptedException {
15 |
16 | while(true) {
17 | synchronized (this) {
18 | while (count == 5) {
19 | log.info("count == 5 , wait ....");
20 | wait();
21 | }
22 | count++;
23 | log.info("produce count {}", count);
24 | notify();
25 | }
26 | }
27 | }
28 |
29 | public void consumeMessage() throws InterruptedException {
30 |
31 | while (true) {
32 | synchronized (this) {
33 | while (count == 0) {
34 | log.info("count == 0, wait ...");
35 | wait();
36 | }
37 | log.info("consume count {}", count);
38 | count--;
39 | notify();
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/wait-sleep/src/main/java/com/flydean/WaitUsage.java:
--------------------------------------------------------------------------------
1 | package com.flydean;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | /**
6 | * @author wayne
7 | * @version WaitUsage, 2020/2/29 8:53 上午
8 | */
9 | @Slf4j
10 | public class WaitUsage {
11 |
12 | private static Object LOCK = new Object();
13 |
14 | public static void WaitExample() throws InterruptedException {
15 | synchronized (LOCK) {
16 | LOCK.wait(1000);
17 | log.info("Object '" + LOCK + "' is woken after" +
18 | " waiting for 1 second");
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/wait-sleep/src/test/java/WaitUsageTest.java:
--------------------------------------------------------------------------------
1 | import com.flydean.WaitNotifyUsage;
2 | import com.flydean.WaitUsage;
3 | import org.junit.Test;
4 |
5 | import java.util.concurrent.ExecutorService;
6 | import java.util.concurrent.Executors;
7 |
8 | /**
9 | * @author wayne
10 | * @version WaitUsageTest, 2020/2/29 9:18 上午
11 | */
12 | public class WaitUsageTest {
13 |
14 | @Test
15 | public void testWaitUsage() throws InterruptedException {
16 | WaitUsage.WaitExample();
17 | }
18 |
19 | @Test
20 | public void testWaitNotifyUsage() throws InterruptedException{
21 | WaitNotifyUsage waitNotifyUsage=new WaitNotifyUsage();
22 |
23 | ExecutorService executorService=Executors.newFixedThreadPool(4);
24 | executorService.submit(()-> {
25 | try {
26 | waitNotifyUsage.produceMessage();
27 | } catch (InterruptedException e) {
28 | e.printStackTrace();
29 | }
30 | });
31 |
32 | executorService.submit(()-> {
33 | try {
34 | waitNotifyUsage.consumeMessage();
35 | } catch (InterruptedException e) {
36 | e.printStackTrace();
37 | }
38 | });
39 |
40 | Thread.sleep(50000);
41 |
42 |
43 | }
44 | }
45 |
--------------------------------------------------------------------------------