├── .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 ![Github stars](https://img.shields.io/github/stars/ddean2009/learn-java-concurrency.svg)一下,谢谢 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 | --------------------------------------------------------------------------------