├── .gitignore ├── README.md ├── pom.xml └── src ├── main ├── java │ └── org │ │ └── banyan │ │ ├── concurrent │ │ ├── ThreadPoolInvokeAllTaskTest.java │ │ ├── assembly │ │ │ ├── Test.java │ │ │ └── hsdis-amd64.dylib │ │ ├── base │ │ │ ├── ConcurrentCollectionTest.java │ │ │ ├── ConcurrentHashMapTest.java │ │ │ ├── ConcurrentUtils.java │ │ │ ├── DeprecatedSuspendResume.java │ │ │ ├── ForkJoinTest.java │ │ │ ├── GenericService.java │ │ │ ├── LinkedListTest.java │ │ │ ├── ListUtil.java │ │ │ ├── MemoryModelVisibleTest.java │ │ │ ├── SaleTicketThread.java │ │ │ ├── SyncMinHoldTimeDemo.java │ │ │ ├── UnsafeDemo.java │ │ │ └── computetask │ │ │ │ ├── Client.java │ │ │ │ ├── Computable.java │ │ │ │ ├── ComputeDefault.java │ │ │ │ └── ComputeWrapper.java │ │ ├── combination │ │ │ ├── DelegatingVehicleTracker.java │ │ │ ├── ImprovedList.java │ │ │ ├── ListHelper.java │ │ │ ├── RateLimiter.java │ │ │ └── VisualComponent.java │ │ ├── domain │ │ │ └── Message.java │ │ ├── example │ │ │ └── matrix │ │ │ │ ├── MatrixGenerator.java │ │ │ │ ├── SerialMain.java │ │ │ │ ├── SerialMultiplier.java │ │ │ │ ├── StrTest.java │ │ │ │ └── parallel │ │ │ │ ├── individual │ │ │ │ ├── ClientMain.java │ │ │ │ ├── IndividualMultiplierTask.java │ │ │ │ └── ParallelIndividualMultiplier.java │ │ │ │ └── row │ │ │ │ ├── ClientMain.java │ │ │ │ ├── ParallelRowMultiplier.java │ │ │ │ └── RowMultiplierTask.java │ │ ├── future │ │ │ ├── CompletableFutureDemo.java │ │ │ ├── FutureTaskDemo.java │ │ │ ├── UsingCompletableFuture.java │ │ │ ├── completablefuture │ │ │ │ ├── CompletableFutureTest.java │ │ │ │ ├── FutureTest.java │ │ │ │ ├── model │ │ │ │ │ ├── MedalInfo.java │ │ │ │ │ └── UserInfo.java │ │ │ │ └── service │ │ │ │ │ ├── MedalService.java │ │ │ │ │ └── UserInfoService.java │ │ │ └── simple │ │ │ │ ├── BizData.java │ │ │ │ ├── Client.java │ │ │ │ └── FutureBizData.java │ │ ├── interrupt │ │ │ ├── InterruptCheck.java │ │ │ ├── InterruptReset.java │ │ │ ├── PendingInterrupt.java │ │ │ └── SleepInterrupt.java │ │ ├── jol │ │ │ ├── JolExample.java │ │ │ └── User.java │ │ ├── jvm │ │ │ ├── CmsGcLogTest.java │ │ │ ├── CpuHighLoadTest.java │ │ │ ├── DeathLockTest.java │ │ │ ├── OutOfMemoryTest.java │ │ │ └── TestStackDeep.java │ │ ├── lambda │ │ │ ├── Interface1.java │ │ │ └── Sort1.java │ │ ├── lock │ │ │ ├── BasicObjectLockTest.java │ │ │ ├── BiasedLock.java │ │ │ ├── BoundedHashSet.java │ │ │ ├── CountDownLatchDemo.java │ │ │ ├── CyclicBarrierDemo.java │ │ │ ├── DeadLockAvoid.java │ │ │ ├── DeadLockDemo.java │ │ │ ├── LazyInitSingleton.java │ │ │ ├── LockSupportDemo.java │ │ │ ├── MutexLockWithAQS.java │ │ │ ├── ReadWriteLock.java │ │ │ ├── SemaphoreDemo.java │ │ │ ├── SeparationLock.java │ │ │ ├── SimpleLock.java │ │ │ ├── SimpleLockCount.java │ │ │ ├── SpinLock.java │ │ │ ├── TimeConsumingLock.java │ │ │ ├── UsingExplicitReadWriteLocks.java │ │ │ ├── UsingExplicitReentrantLocks.java │ │ │ ├── UsingIntrinsicLocks.java │ │ │ ├── atomic │ │ │ │ └── AtomicIntegerCounter.java │ │ │ ├── lock.md │ │ │ └── reentrant │ │ │ │ ├── Demo1Main.java │ │ │ │ ├── Demo1Service.java │ │ │ │ ├── ProducerConsumerQueue.java │ │ │ │ ├── SynReentrantDemo.java │ │ │ │ └── reentrant.md │ │ ├── masterworker │ │ │ ├── Master.java │ │ │ ├── PlusWorker.java │ │ │ ├── Test.java │ │ │ └── Worker.java │ │ ├── model │ │ │ ├── KeyListener.java │ │ │ ├── MouseListener.java │ │ │ ├── Point.java │ │ │ └── xml │ │ │ │ └── XMLSerializerTest.java │ │ ├── objectshare │ │ │ ├── NoVisibility.java │ │ │ └── SafePublish.java │ │ ├── pattern │ │ │ └── condition_queues │ │ │ │ ├── ExplicitConditionQueue.java │ │ │ │ └── WaitNotifyQueue.java │ │ ├── producerconsumer │ │ │ ├── ClientMain.java │ │ │ ├── Consumer.java │ │ │ ├── MessageQueue.java │ │ │ └── Producer.java │ │ ├── queue │ │ │ ├── BoundedBufferQueue.java │ │ │ ├── BoundedBufferQueueTest.java │ │ │ ├── ConsumerProducer.java │ │ │ ├── Java_bloking_queue.md │ │ │ └── ProducerConsumerStack.java │ │ ├── reentrant │ │ │ ├── ReentrantLockDemo.java │ │ │ ├── ReentrantLockSynchronizedDemo.java │ │ │ ├── SpinLock.java │ │ │ ├── SpinLock2.java │ │ │ └── SpinLockTest.java │ │ ├── reference │ │ │ └── WeakReferenceExam.java │ │ ├── resourcepool │ │ │ ├── ResourcePool.java │ │ │ └── ResourcePoolUsage.java │ │ ├── sort │ │ │ ├── EvenOddOutputThread.java │ │ │ ├── FundNetValue.java │ │ │ ├── SortMain.java │ │ │ └── SortTask.java │ │ ├── sync │ │ │ ├── SynIntrinsic.java │ │ │ ├── SynObjectMain.java │ │ │ ├── UsingBarriers.java │ │ │ └── UsingLatches.java │ │ ├── task │ │ │ ├── CallableFuture.java │ │ │ ├── CallableFutureTask.java │ │ │ ├── README.md │ │ │ └── async │ │ │ │ ├── DefaultTaskPromise.java │ │ │ │ ├── TaskCallback.java │ │ │ │ ├── TaskFuture.java │ │ │ │ ├── TaskPromise.java │ │ │ │ └── Test.java │ │ ├── thread │ │ │ ├── CountThread.java │ │ │ ├── PipedStream.java │ │ │ ├── ThreadDaemon.java │ │ │ ├── ThreadDeprecated.java │ │ │ ├── ThreadInterrupted.java │ │ │ ├── ThreadJoin.java │ │ │ ├── ThreadMXBeanExample.java │ │ │ ├── ThreadPriority.java │ │ │ ├── ThreadShutdown.java │ │ │ ├── ThreadState.java │ │ │ ├── ThreadYield.java │ │ │ ├── WaitNotify.java │ │ │ ├── interrupt │ │ │ │ ├── Buffer.java │ │ │ │ ├── BufferInterruptibly.java │ │ │ │ ├── Read.java │ │ │ │ ├── Test.java │ │ │ │ ├── ThreadInterrupt.java │ │ │ │ └── Write.java │ │ │ ├── pool │ │ │ │ ├── CompletionServiceTest.java │ │ │ │ ├── Connection.java │ │ │ │ ├── ConnectionPool.java │ │ │ │ ├── ConnectionPoolTest.java │ │ │ │ ├── DefaultThreadPool.java │ │ │ │ ├── KnowThreadPoolExecutor.java │ │ │ │ ├── NamedThreadFactory.java │ │ │ │ ├── ThreadPool.java │ │ │ │ ├── WorkerThreadTest.java │ │ │ │ └── thread pool.md │ │ │ ├── readme.md │ │ │ ├── search │ │ │ │ ├── Client.java │ │ │ │ ├── CrawlerThread.java │ │ │ │ └── IndexThread.java │ │ │ ├── sleep │ │ │ │ └── SleepTest.java │ │ │ └── waitnotify │ │ │ │ └── EvenOddInWaitNotify.java │ │ ├── threadlocal │ │ │ ├── TLExam1.java │ │ │ ├── TLExam2.java │ │ │ ├── TLExam3.java │ │ │ └── ThreadSafeDateFormat.java │ │ ├── threadpool │ │ │ ├── FixedThreadPoolScene.java │ │ │ ├── PThread.java │ │ │ ├── SimParallelThreadPool.java │ │ │ ├── SimpleThread.java │ │ │ ├── ThreadPool.java │ │ │ └── UsingExecutors.java │ │ └── util │ │ │ └── SleepUtil.java │ │ ├── features │ │ ├── atomics │ │ │ └── UsingAtomics.java │ │ ├── collections │ │ │ ├── UsingConcurrentCollections.java │ │ │ └── UsingSynchronizedCollections.java │ │ ├── executors │ │ │ └── UsingExecutors.java │ │ ├── futures │ │ │ ├── UsingCompletableFuture.java │ │ │ └── UsingFutureTasks.java │ │ ├── java_memory_model │ │ │ └── WhatIsJavaMemoryModel.java │ │ ├── locks │ │ │ ├── UsingExplicitReadWriteLocks.java │ │ │ ├── UsingExplicitReentrantLocks.java │ │ │ └── UsingIntrinsicLocks.java │ │ ├── synchronizers │ │ │ ├── UsingBarriers.java │ │ │ ├── UsingLatches.java │ │ │ └── UsingSemaphores.java │ │ └── threads │ │ │ ├── Test.java │ │ │ └── UsingThreads.java │ │ └── patterns │ │ ├── GuardedBy.java │ │ ├── ThreadSafe.java │ │ ├── condition_queues │ │ ├── ExplicitConditionQueue.java │ │ └── WaitNotifyQueue.java │ │ ├── controlled_initialization │ │ └── ControlledInitialization.java │ │ ├── fixed_lock_ordering │ │ ├── CoinTransfer.java │ │ └── FixedLockOrdering.java │ │ ├── non_blocking │ │ ├── DoubleCounter.java │ │ └── NonBlockingDesign.java │ │ ├── producer_consumer │ │ └── ProducerConsumer.java │ │ ├── resource_pool │ │ ├── ResourcePool.java │ │ └── ResourcePoolUsage.java │ │ ├── task_cancel │ │ ├── BackgroundTimePrintTask.java │ │ └── ThreadTaskCancel.java │ │ ├── task_convergence │ │ └── TaskConvergence.java │ │ ├── task_execution │ │ └── BackgroundTaskExecutor.java │ │ └── thread_safe │ │ ├── DateUtil.java │ │ ├── compound_actions │ │ ├── AtomicCompoundActions.java │ │ └── CompareAndSwapUtil.java │ │ ├── immutable_object │ │ ├── EventKeeper.java │ │ └── ImmutableObject.java │ │ ├── initialization │ │ └── SafeInitializationHolder.java │ │ ├── lock_split │ │ ├── LockSplit.java │ │ └── OSToolConfiguration.java │ │ ├── publishing │ │ └── SafePublishing.java │ │ ├── shared_state │ │ ├── ProtectedSharedState.java │ │ └── VisitCounter.java │ │ └── thread_confinement │ │ ├── ThreadLocalConfinement.java │ │ └── ThreadSafeDateFormat.java └── resources │ ├── diagram │ ├── AtomicInteger.md │ ├── aaaef'.graffle │ ├── arch_total.png │ ├── concurrency-parallel.jpg │ ├── future1.png │ ├── master-worker.png │ ├── os_progress_thread.graffle │ └── 如何看待对象是否有用.png │ └── md │ ├── C001.md │ ├── concurrent_understand.md │ ├── protocol.md │ ├── reentrantlock.md │ ├── sleep_yield.md │ ├── synchronzied.md │ ├── thread-safe.md │ ├── threadpoll.md │ ├── volatile.md │ └── 并发设计原理.md └── test └── java └── com └── banyan └── test ├── ConcurrencyTest.java ├── Daemon.java ├── DateTimePerformanceTest.java ├── EnumStaticMethod.java ├── FastUtilTest.java ├── GenericServiceTest.java ├── HeapOOM.java ├── IgniteDemo.java ├── JavaVMStackSOF.java ├── ListPartition.java ├── ManagementFactoryTest.java ├── MemoryLeakFutureTaskDemo.java ├── NativeOutOfMemoryErrorTest.java ├── ProducerConsumerQueueTest.java ├── RuntimeConstantPoolOOM.java ├── VolatilePerformanceClientMain.java ├── domain ├── Address.java ├── Detail.java ├── Person.java └── User.java └── thread ├── ExecutorsUtil.java └── ThreadDemo.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.ipr 3 | *.iws 4 | *.iml 5 | *.db 6 | *.log 7 | *.class 8 | *.classpath 9 | *.settings 10 | .project 11 | .idea 12 | log 13 | target/ 14 | *.jar 15 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/ThreadPoolInvokeAllTaskTest.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import java.util.concurrent.*; 7 | 8 | public class ThreadPoolInvokeAllTaskTest { 9 | 10 | public static void invokeAllTask() throws InterruptedException, ExecutionException { 11 | ThreadPoolExecutor executor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 1, TimeUnit.MILLISECONDS, new SynchronousQueue<>()); 12 | List> task = new ArrayList<>(); 13 | for (int i = 1; i <= 5; i++) { 14 | task.add(() -> { 15 | new Say().s(); 16 | return false; 17 | }); 18 | } 19 | 20 | List> futures = executor.invokeAll(task); 21 | for (Future future : futures) { 22 | System.out.println(future.get() + "-----"); 23 | } 24 | } 25 | 26 | public static void main(String[] args) { 27 | try { 28 | invokeAllTask(); 29 | 30 | } catch (Exception e) { 31 | e.printStackTrace(); 32 | } 33 | 34 | // Double dd=1.3145962650000082E7;13145962.650000082 35 | // Double dd=1.314596265E7; 13145962.65 36 | 37 | BigDecimal decimal = new BigDecimal("1.314596265E7"); 38 | System.err.println(decimal.toString()); 39 | 40 | 41 | } 42 | 43 | static class Say { 44 | public void s() { 45 | System.out.println(1111); 46 | } 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/assembly/Test.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.assembly; 2 | 3 | /** 4 | * -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly 5 | * 6 | * @author krisjin 7 | * @date 2020/11/16 8 | */ 9 | public class Test { 10 | 11 | public static void main(String[] args) { 12 | System.out.println(11111); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/assembly/hsdis-amd64.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krisjin/banyan/1762f3b26ce8ff0e451d9bc3b30958226f0679cb/src/main/java/org/banyan/concurrent/assembly/hsdis-amd64.dylib -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/base/ConcurrentUtils.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.base; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.TimeUnit; 5 | 6 | public class ConcurrentUtils { 7 | 8 | public static void stop(ExecutorService executor) { 9 | try { 10 | executor.shutdown(); 11 | executor.awaitTermination(1, TimeUnit.SECONDS); 12 | } catch (InterruptedException e) { 13 | System.err.println("termination interrupted"); 14 | } finally { 15 | if (!executor.isTerminated()) { 16 | System.err.println("killing non-finished tasks"); 17 | } 18 | executor.shutdownNow(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/base/GenericService.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.base; 2 | 3 | /** 4 | * User: krisjin 5 | * Date: 2017/1/3 6 | */ 7 | public class GenericService { 8 | 9 | 10 | /** 11 | * 泛型方法 12 | * 13 | * @param c 用来创建泛型对象 14 | * @param 声明一个泛型T 15 | * @return 16 | * @throws InstantiationException 17 | * @throws IllegalAccessException 18 | */ 19 | public T getObject(Class c) throws InstantiationException, IllegalAccessException { 20 | //创建泛型对象 21 | T t = c.newInstance(); 22 | return t; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/base/LinkedListTest.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.base; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.concurrent.BlockingQueue; 6 | import java.util.concurrent.LinkedBlockingQueue; 7 | import java.util.stream.Collectors; 8 | import java.util.stream.IntStream; 9 | 10 | /** 11 | * @author krisjin 12 | * @date 2020/11/14 13 | */ 14 | public class LinkedListTest { 15 | 16 | public static void main(String[] args) { 17 | List list = new ArrayList<>(); 18 | IntStream.range(1, 100).forEach(i -> list.add(i)); 19 | BlockingQueue blockingQueue = new LinkedBlockingQueue<>(10000); 20 | 21 | List longList = list.stream().parallel() 22 | .map(i -> i.longValue()) 23 | .sorted() 24 | .collect(Collectors.toList()); 25 | 26 | System.out.println("blockingQueue" + blockingQueue.toString()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/base/ListUtil.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.base; 2 | 3 | import com.google.common.collect.Lists; 4 | 5 | import java.text.ParseException; 6 | import java.text.SimpleDateFormat; 7 | import java.util.ArrayList; 8 | import java.util.Date; 9 | import java.util.List; 10 | 11 | public class ListUtil { 12 | 13 | public static void main(String[] args) { 14 | List> userList = Lists.partition(getUserData(), 2); 15 | System.out.println(userList.size()); 16 | String dt = "2021-09-17"; 17 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 18 | try { 19 | Date d = sdf.parse(dt); 20 | System.err.println(d); 21 | } catch (ParseException e) { 22 | e.printStackTrace(); 23 | } 24 | } 25 | 26 | public static List getUserData() { 27 | List userDatas = new ArrayList<>(); 28 | userDatas.add(new UserData()); 29 | userDatas.add(new UserData()); 30 | userDatas.add(new UserData()); 31 | userDatas.add(new UserData()); 32 | userDatas.add(new UserData()); 33 | return userDatas; 34 | 35 | } 36 | 37 | public static class UserData { 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/base/MemoryModelVisibleTest.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.base; 2 | 3 | /** 4 | * User:krisjin 5 | * Date:2020-04-16 6 | */ 7 | public class MemoryModelVisibleTest { 8 | private int i = 0; 9 | private int j = 0; 10 | // 当前的k被设置为volatile ,i,j变量都将被设置为happens-before关系 11 | // 确保k被更改后,之前的i,j都已经保证被赋值了, 变量的顺序 12 | private volatile boolean k = false; 13 | 14 | //线程1设置新值 15 | private void thread1() { 16 | new Thread(() -> { 17 | i = 1; 18 | j = 2; 19 | k = true; 20 | }).start(); 21 | } 22 | 23 | //线程2读取新值 24 | private void thread2() { 25 | new Thread(() -> { 26 | String s = "i=" + i + ", j=" + j;//i ,j 从主内存获取最新并更新到本地内存 27 | System.out.println(s); 28 | }).start(); 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/base/SaleTicketThread.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.base; 2 | 3 | /** 4 | * 非线程安全 5 | */ 6 | public class SaleTicketThread implements Runnable { 7 | private int ticketNum = 5; 8 | 9 | //主线程 10 | public static void main(String[] args) { 11 | SaleTicketThread saleTicketThread = new SaleTicketThread(); 12 | new Thread(saleTicketThread, "saler_1").start(); 13 | new Thread(saleTicketThread, "saler_2").start(); 14 | new Thread(saleTicketThread, "saler_3").start(); 15 | 16 | } 17 | 18 | @Override 19 | public void run() { 20 | for (int i = 0; i <= 10; i++) { 21 | if (ticketNum > 0) { 22 | System.out.println(Thread.currentThread().getName() + " priority " + Thread.currentThread().getPriority() + " sale ticket,current ticket num is " + ticketNum--); 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/base/SyncMinHoldTimeDemo.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.base; 2 | 3 | /** 4 | * 减少线程持有锁的时间,它是一种在并发编程中需要注意的小技巧经验 5 | * https://mp.weixin.qq.com/s/0mpCtq5CxKWABSR_ASnNCA 6 | * User: krisjin 7 | * Date: 2021/6/2 8 | */ 9 | public class SyncMinHoldTimeDemo { 10 | public void a() { 11 | } 12 | 13 | public void b() { 14 | } 15 | 16 | public void mutexMethod() { 17 | } 18 | 19 | public synchronized void sync1() { 20 | a();//不存在线程安全影响 21 | mutexMethod();//需要互斥、保证程序正确性 22 | b();//不存在线程安全影响 23 | } 24 | 25 | public void sync2() { 26 | a();//不存在线程安全影响 27 | synchronized (this) { 28 | mutexMethod();//需要互斥、保证程序正确性 29 | } 30 | b();//不存在线程安全影响 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/base/computetask/Client.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.base.computetask; 2 | 3 | import org.banyan.concurrent.util.SleepUtil; 4 | 5 | import java.util.concurrent.ExecutionException; 6 | 7 | public class Client { 8 | 9 | public static void main(String[] args) throws ExecutionException, InterruptedException { 10 | Computable computable = new ComputeDefault();//实例化默认计算实现 11 | //创建一个缓存计算包装器,包装器的构造参数为计算接口 12 | ComputeWrapper computeWrapper = new ComputeWrapper(computable); 13 | int val = computeWrapper.compute(11); 14 | System.out.println("第一次计算值:" + val); 15 | SleepUtil.second(2); 16 | val = computeWrapper.compute(12); //第二次从缓存获取 17 | System.out.println("第二次计算值:" + val); 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/base/computetask/Computable.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.base.computetask; 2 | 3 | import java.util.concurrent.ExecutionException; 4 | 5 | /** 6 | * 计算接口定义 7 | * 接口定义,A为参数,V为定义的结果 8 | */ 9 | public interface Computable { 10 | 11 | V compute(A param) throws InterruptedException, ExecutionException; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/base/computetask/ComputeDefault.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.base.computetask; 2 | 3 | import org.banyan.concurrent.util.SleepUtil; 4 | 5 | /** 6 | * 默认计算功能实现 7 | */ 8 | public class ComputeDefault implements Computable { 9 | 10 | @Override 11 | public Integer compute(Integer param) { 12 | int result = param + 1; 13 | SleepUtil.second(3); 14 | return result; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/base/computetask/ComputeWrapper.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.base.computetask; 2 | 3 | import java.util.concurrent.*; 4 | 5 | /** 6 | * 包装器模式 7 | * 计算结果缓存包装器,实现Computable接口 8 | */ 9 | public class ComputeWrapper implements Computable { 10 | 11 | //结果缓存 12 | private final ConcurrentMap> cache = new ConcurrentHashMap>(); 13 | //计算接口 14 | private final Computable computable; 15 | 16 | //包装器传入计算接口 17 | public ComputeWrapper(Computable computable) { 18 | this.computable = computable; 19 | } 20 | 21 | @Override 22 | public V compute(final A param) throws InterruptedException, ExecutionException { 23 | while (true) { 24 | Future future = cache.get(param); 25 | if (future == null) { 26 | Callable callable = (() -> computable.compute(param)); 27 | FutureTask futureTask = new FutureTask(callable); 28 | future = cache.putIfAbsent(param, futureTask); 29 | if (future == null) { 30 | future = futureTask; 31 | futureTask.run(); 32 | } 33 | } else { 34 | System.out.println("###################cache hit###################"); 35 | } 36 | return future.get(); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/combination/DelegatingVehicleTracker.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.combination; 2 | 3 | import org.banyan.concurrent.model.Point; 4 | 5 | import java.math.BigDecimal; 6 | import java.math.RoundingMode; 7 | import java.util.Collections; 8 | import java.util.Map; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | import java.util.concurrent.ConcurrentMap; 11 | 12 | /** 13 | * 将线程安全委托给ConcurrentHashMap 14 | */ 15 | public class DelegatingVehicleTracker { 16 | 17 | private final ConcurrentMap locations; 18 | private final Map unModifyAbleMap; 19 | 20 | /** 21 | * 构造函数初始化,保证线程的安全性。 22 | * 23 | * @param map 24 | */ 25 | public DelegatingVehicleTracker(Map map) { 26 | locations = new ConcurrentHashMap<>(map); 27 | unModifyAbleMap = Collections.unmodifiableMap(locations); 28 | } 29 | 30 | public Map getLocations() { 31 | return unModifyAbleMap; 32 | } 33 | 34 | public Point getLocation(String id) { 35 | return locations.get(id); 36 | } 37 | 38 | public void setLocation(String id, int x, int y) { 39 | if (locations.replace(id, new Point(x, y)) == null) { 40 | throw new IllegalArgumentException("invalid vehicle name : " + id); 41 | } 42 | } 43 | 44 | public static void main(String[] args) { 45 | String s = "1.3641936E7"; 46 | BigDecimal bd = new BigDecimal(s); 47 | bd.setScale(2, RoundingMode.FLOOR); 48 | System.err.println(bd.doubleValue()); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/combination/ListHelper.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.combination; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | /** 8 | * 客户端加锁机制,通过客户端加锁实现“若没则添加” 9 | */ 10 | public class ListHelper { 11 | 12 | public List list = Collections.synchronizedList(new ArrayList()); 13 | 14 | public boolean putIfAbsent(E e) { 15 | synchronized (list) { 16 | boolean absent = !list.contains(e); 17 | if (absent) { 18 | list.add(e); 19 | } 20 | return absent; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/combination/RateLimiter.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.combination; 2 | 3 | import java.util.concurrent.Semaphore; 4 | 5 | public class RateLimiter { 6 | private final Semaphore semaphore; 7 | private final int maxPermits; 8 | private long lastRefillTime; 9 | private final long refillInterval; 10 | 11 | public RateLimiter(int maxPermits, long refillInterval) { 12 | this.maxPermits = maxPermits; 13 | this.refillInterval = refillInterval; 14 | this.semaphore = new Semaphore(maxPermits); 15 | this.lastRefillTime = System.currentTimeMillis(); 16 | } 17 | 18 | public void acquire() throws InterruptedException { 19 | if (System.currentTimeMillis() - lastRefillTime >= refillInterval) { 20 | refill(); 21 | } 22 | semaphore.acquire(); 23 | } 24 | 25 | public void release() { 26 | semaphore.release(); 27 | } 28 | 29 | private void refill() { 30 | long now = System.currentTimeMillis(); 31 | long elapsedTime = now - lastRefillTime; 32 | int permitsToAdd = (int) (elapsedTime / refillInterval * maxPermits); 33 | for (int i = 0; i < permitsToAdd; i++) { 34 | semaphore.release(); 35 | } 36 | lastRefillTime = now; 37 | } 38 | 39 | public static void main(String[] args) { 40 | RateLimiter rateLimiter = new RateLimiter(5, 1); 41 | 42 | for (int i = 0; i < 10000; i++) { 43 | try { 44 | rateLimiter.acquire(); 45 | System.out.println("请求 " + (i + 1) + " 被允许"); 46 | Thread.sleep(200); 47 | } catch (InterruptedException e) { 48 | e.printStackTrace(); 49 | } finally { 50 | rateLimiter.release(); 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/combination/VisualComponent.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.combination; 2 | 3 | import org.banyan.concurrent.model.KeyListener; 4 | import org.banyan.concurrent.model.MouseListener; 5 | 6 | import java.util.List; 7 | import java.util.concurrent.CopyOnWriteArrayList; 8 | 9 | /** 10 | * 将线程安全性委托给多状态变量 11 | */ 12 | public class VisualComponent { 13 | 14 | private final List keyListeners = new CopyOnWriteArrayList(); 15 | 16 | private final List mouseListeners = new CopyOnWriteArrayList(); 17 | 18 | public void addKeyListener(KeyListener keyListener) { 19 | keyListeners.add(keyListener); 20 | } 21 | 22 | public void addMouseListener(MouseListener mouseListener) { 23 | mouseListeners.add(mouseListener); 24 | } 25 | 26 | public boolean removeKeyListener(KeyListener keyListener) { 27 | return keyListeners.remove(keyListener); 28 | } 29 | 30 | public boolean removeMouseListener(MouseListener mouseListener) { 31 | return mouseListeners.remove(mouseListener); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/domain/Message.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.domain; 2 | 3 | 4 | public class Message { 5 | private String msg; 6 | 7 | public String getMsg() { 8 | return msg; 9 | } 10 | 11 | public void setMsg(String msg) { 12 | this.msg = msg; 13 | } 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/example/matrix/MatrixGenerator.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.example.matrix; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * User:krisjin 7 | * Date:2019/3/10 8 | */ 9 | public class MatrixGenerator { 10 | 11 | /** 12 | * 随机生成矩阵 13 | * 14 | * @param rows 15 | * @param columns 16 | * @return 17 | */ 18 | public static double[][] generate(int rows, int columns) { 19 | double[][] ret = new double[rows][columns]; 20 | Random random = new Random(); 21 | 22 | for (int i = 0; i < rows; i++) { 23 | for (int j = 0; j < columns; j++) { 24 | ret[i][j] = random.nextDouble() * 10; 25 | } 26 | } 27 | return ret; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/example/matrix/SerialMain.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.example.matrix; 2 | 3 | /** 4 | * User:krisjin 5 | * Date:2019/3/10 6 | */ 7 | public class SerialMain { 8 | 9 | public static void main(String[] args) { 10 | 11 | double[][] matrix1 = MatrixGenerator.generate(10, 10); 12 | double[][] matrix2 = MatrixGenerator.generate(10, 10); 13 | 14 | double[][] result = new double[matrix1.length][matrix2[0].length]; 15 | long st = System.currentTimeMillis(); 16 | SerialMultiplier.multiply(matrix1, matrix2, result); 17 | 18 | System.out.println("Serial:" + (System.currentTimeMillis() - st)); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/example/matrix/SerialMultiplier.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.example.matrix; 2 | 3 | /** 4 | * User:krisjin 5 | * Date:2019/3/10 6 | */ 7 | public class SerialMultiplier { 8 | 9 | public static void multiply(double[][] matrix1, double[][] matrix2, double[][] result) { 10 | 11 | int row1 = matrix1.length; 12 | int columns1 = matrix1[0].length; 13 | 14 | int columns2 = matrix2[0].length; 15 | 16 | for (int i = 0; i < row1; i++) { 17 | for (int j = 0; j < columns2; j++) { 18 | result[i][j] = 0; 19 | for (int k = 0; k < columns1; k++) { 20 | result[i][j] += matrix1[i][k] * matrix2[k][j]; 21 | } 22 | 23 | } 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/example/matrix/StrTest.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.example.matrix; 2 | 3 | /** 4 | * @author kris 5 | * @date 2023/10/19 6 | */ 7 | public class StrTest { 8 | 9 | public static void main(String[] args) { 10 | String s="刘爱华提交的南通市产品质量监督检验所(国家钢丝绳产品质量监督检验中心、江苏省电机产品质量监督检验中心、江苏省电动工具产品质量监督检验中心、江苏省缺陷产品管理技术中心南通分中心)频道开通申请"; 11 | 12 | StringBuilder sb = new StringBuilder(); 13 | sb.append(11).append(22); 14 | 15 | 16 | System.out.println(s.length()); 17 | System.out.println(s.getBytes().length); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/example/matrix/parallel/individual/ClientMain.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.example.matrix.parallel.individual; 2 | 3 | import org.banyan.concurrent.example.matrix.MatrixGenerator; 4 | 5 | /** 6 | * User:krisjin 7 | * Date:2019/3/11 8 | */ 9 | public class ClientMain { 10 | 11 | public static void main(String[] args) { 12 | 13 | double[][] matrix1 = MatrixGenerator.generate(2000, 2000); 14 | double[][] matrix2 = MatrixGenerator.generate(2000, 2000); 15 | 16 | double[][] result = new double[matrix1.length][matrix2[0].length]; 17 | long st = System.currentTimeMillis(); 18 | ParallelIndividualMultiplier.multiply(matrix1, matrix2, result); 19 | 20 | System.out.println("Parallel individual:" + (System.currentTimeMillis() - st)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/example/matrix/parallel/individual/IndividualMultiplierTask.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.example.matrix.parallel.individual; 2 | 3 | /** 4 | * User:krisjin 5 | * Date:2019/3/11 6 | */ 7 | public class IndividualMultiplierTask implements Runnable { 8 | private final double[][] result; 9 | private final double[][] matrix1; 10 | private final double[][] matrix2; 11 | 12 | private final int row; 13 | private final int column; 14 | 15 | public IndividualMultiplierTask(double[][] result, double[][] matrix1, double[][] matrix2, int i, int j) { 16 | this.result = result; 17 | this.matrix1 = matrix1; 18 | this.matrix2 = matrix2; 19 | this.row = i; 20 | this.column = j; 21 | } 22 | 23 | @Override 24 | public void run() { 25 | result[row][column] = 0; 26 | for (int k = 0; k < matrix1[row].length; k++) { 27 | result[row][column] += matrix1[row][k] * matrix2[k][column]; 28 | } 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/example/matrix/parallel/individual/ParallelIndividualMultiplier.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.example.matrix.parallel.individual; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * User:krisjin 8 | * Date:2019/3/11 9 | *   10 | */ 11 | public class ParallelIndividualMultiplier { 12 | 13 | public static void multiply(double[][] matrix1, double[][] matrix2, double[][] result) { 14 | 15 | List threads = new ArrayList<>(); 16 | 17 | int rows1 = matrix1.length; 18 | int columns1 = matrix1[0].length; 19 | 20 | int rows2 = matrix2.length; 21 | int columns2 = matrix2[0].length; 22 | 23 | for (int i = 0; i < rows1; i++) { 24 | for (int j = 0; j < columns2; j++) { 25 | IndividualMultiplierTask task = new IndividualMultiplierTask(result, matrix1, matrix2, i, j); 26 | Thread thread = new Thread(task); 27 | thread.start(); 28 | threads.add(thread); 29 | 30 | if (threads.size() % 10 == 0) { 31 | waitForThreads(threads); 32 | } 33 | } 34 | } 35 | 36 | } 37 | 38 | private static void waitForThreads(List threads) { 39 | for (Thread thread : threads) { 40 | try { 41 | thread.join(); 42 | } catch (InterruptedException e) { 43 | e.printStackTrace(); 44 | } 45 | } 46 | 47 | threads.clear(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/example/matrix/parallel/row/ClientMain.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.example.matrix.parallel.row; 2 | 3 | import org.banyan.concurrent.example.matrix.MatrixGenerator; 4 | 5 | /** 6 | * User:krisjin 7 | * Date:2019/3/11 8 | */ 9 | public class ClientMain { 10 | 11 | public static void main(String[] args) { 12 | 13 | double[][] matrix1 = MatrixGenerator.generate(2000, 2000); 14 | double[][] matrix2 = MatrixGenerator.generate(2000, 2000); 15 | 16 | double[][] result = new double[matrix1.length][matrix2[0].length]; 17 | long st = System.currentTimeMillis(); 18 | ParallelRowMultiplier.multiply(matrix1, matrix2, result); 19 | 20 | System.out.println("Parallel Row:" + (System.currentTimeMillis() - st)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/example/matrix/parallel/row/ParallelRowMultiplier.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.example.matrix.parallel.row; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * User:krisjin 8 | * Date:2019/3/11 9 | *   10 | */ 11 | public class ParallelRowMultiplier { 12 | 13 | 14 | public static void multiply(double[][] matrix1, double[][] matrix2, double[][] result) { 15 | 16 | List threads = new ArrayList<>(); 17 | 18 | int rows1 = matrix1.length; 19 | int columns1 = matrix1[0].length; 20 | 21 | int rows2 = matrix2.length; 22 | int columns2 = matrix2[0].length; 23 | 24 | for (int i = 0; i < rows1; i++) { 25 | RowMultiplierTask task = new RowMultiplierTask(result, matrix1, matrix2, i); 26 | Thread thread = new Thread(task); 27 | thread.start(); 28 | threads.add(thread); 29 | 30 | if (threads.size() % 10 == 0) { 31 | waitForThreads(threads); 32 | } 33 | } 34 | } 35 | 36 | private static void waitForThreads(List threads) { 37 | for (Thread thread : threads) { 38 | try { 39 | thread.join(); 40 | } catch (InterruptedException e) { 41 | e.printStackTrace(); 42 | } 43 | } 44 | 45 | threads.clear(); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/example/matrix/parallel/row/RowMultiplierTask.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.example.matrix.parallel.row; 2 | 3 | /** 4 | * User:krisjin 5 | * Date:2019/3/11 6 | *   7 | */ 8 | public class RowMultiplierTask implements Runnable { 9 | 10 | 11 | private final double[][] result; 12 | private final double[][] matrix1; 13 | private final double[][] matrix2; 14 | 15 | private final int row; 16 | 17 | public RowMultiplierTask(double[][] result, double[][] matrix1, double[][] matrix2, int i) { 18 | this.result = result; 19 | this.matrix1 = matrix1; 20 | this.matrix2 = matrix2; 21 | this.row = i; 22 | } 23 | 24 | public void run() { 25 | for (int j = 0; j < matrix2[0].length; j++) { 26 | result[row][j] = 0; 27 | for (int k = 0; k < matrix1[row].length; k++) { 28 | result[row][j] += matrix1[row][k] * matrix2[k][j]; 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/future/FutureTaskDemo.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.future; 2 | 3 | import java.util.concurrent.*; 4 | 5 | /** 6 | * Future模式的核心在于去除了主函数的等待时间,利用原来等待的时间处理其它逻辑 7 | */ 8 | public class FutureTaskDemo { 9 | 10 | public static void main(String[] args) throws ExecutionException, InterruptedException { 11 | FutureTask future = new FutureTask(new StrTask("Hello")); 12 | ExecutorService executorService = Executors.newFixedThreadPool(1); 13 | executorService.submit(future); 14 | System.out.println("任务已提交"); 15 | System.out.println(getName()); 16 | System.out.println(future.get()); 17 | 18 | executorService.shutdown(); 19 | } 20 | 21 | static class StrTask implements Callable { 22 | private String str; 23 | 24 | public StrTask(String str) { 25 | this.str = str; 26 | } 27 | 28 | @Override 29 | public String call() throws InterruptedException { 30 | TimeUnit.SECONDS.sleep(5); 31 | return this.str + " world!"; 32 | } 33 | } 34 | 35 | static String getName() throws InterruptedException { 36 | TimeUnit.SECONDS.sleep(2); 37 | return "kris"; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/future/completablefuture/CompletableFutureTest.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.future.completablefuture; 2 | 3 | import org.banyan.concurrent.future.completablefuture.model.MedalInfo; 4 | import org.banyan.concurrent.future.completablefuture.model.UserInfo; 5 | import org.banyan.concurrent.future.completablefuture.service.MedalService; 6 | import org.banyan.concurrent.future.completablefuture.service.UserInfoService; 7 | 8 | import java.util.concurrent.CompletableFuture; 9 | import java.util.concurrent.ExecutionException; 10 | import java.util.concurrent.TimeUnit; 11 | import java.util.concurrent.TimeoutException; 12 | 13 | /** 14 | * 15 | */ 16 | public class CompletableFutureTest { 17 | 18 | public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException { 19 | 20 | UserInfoService userInfoService = new UserInfoService(); 21 | MedalService medalService = new MedalService(); 22 | long userId = 666L; 23 | long startTime = System.currentTimeMillis(); 24 | 25 | CompletableFuture completableUserInfoFuture = CompletableFuture.supplyAsync(() -> userInfoService.getUserInfo(userId)); 26 | 27 | Thread.sleep(300); 28 | 29 | CompletableFuture completableMedalInfoFuture = CompletableFuture.supplyAsync(() -> medalService.getMedalInfo(userId)); 30 | 31 | UserInfo userInfo = completableUserInfoFuture.get(2, TimeUnit.SECONDS); 32 | MedalInfo medalInfo = completableMedalInfoFuture.get(); 33 | System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms"); 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/future/completablefuture/model/MedalInfo.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.future.completablefuture.model; 2 | 3 | /** 4 | * @author kris 5 | * @date 2023/4/2 6 | */ 7 | public class MedalInfo { 8 | private String id; 9 | private String name; 10 | 11 | public MedalInfo(String id, String name) { 12 | this.id = id; 13 | this.name = name; 14 | } 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/future/completablefuture/model/UserInfo.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.future.completablefuture.model; 2 | 3 | /** 4 | * @author kris 5 | * @date 2023/4/2 6 | */ 7 | public class UserInfo { 8 | private String id; 9 | private String name; 10 | private int age; 11 | 12 | public UserInfo(String id, String name, Integer age) { 13 | this.id = id; 14 | this.name = name; 15 | this.age = age; 16 | } 17 | 18 | public String getName() { 19 | return name; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/future/completablefuture/service/MedalService.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.future.completablefuture.service; 2 | 3 | import org.banyan.concurrent.future.completablefuture.model.MedalInfo; 4 | 5 | public class MedalService { 6 | 7 | public MedalInfo getMedalInfo(long userId) { 8 | try { 9 | Thread.sleep(500); 10 | } catch (InterruptedException e) { 11 | throw new RuntimeException(e); 12 | } 13 | return new MedalInfo("111", "会员"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/future/completablefuture/service/UserInfoService.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.future.completablefuture.service; 2 | 3 | import org.banyan.concurrent.future.completablefuture.model.UserInfo; 4 | 5 | public class UserInfoService { 6 | 7 | public UserInfo getUserInfo(Long userId) { 8 | try { 9 | Thread.sleep(300); 10 | } catch (InterruptedException e) { 11 | throw new RuntimeException(e); 12 | } 13 | return new UserInfo("111", "星空", 27); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/future/simple/BizData.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.future.simple; 2 | 3 | import org.banyan.concurrent.util.SleepUtil; 4 | 5 | public class BizData { 6 | private final String result; 7 | 8 | public BizData(String para) { 9 | //使用sleep,代替一个很慢的操作过程 10 | SleepUtil.second(3); 11 | result = "hi," + para; 12 | } 13 | 14 | public String getResult() { 15 | return result; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/future/simple/Client.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.future.simple; 2 | 3 | public class Client { 4 | private FutureBizData futureBizData = new FutureBizData(); 5 | 6 | public static void main(String[] args) { 7 | Client client = new Client(); 8 | FutureBizData data = client.request("kris");//立即返回 9 | 10 | System.out.println("获取业务数据任务已提交并返回"); 11 | System.out.println("data=" + data.getResult()); 12 | } 13 | 14 | 15 | public FutureBizData request(final String queryStr) { 16 | new Thread() { 17 | public void run() { 18 | BizData bizData = new BizData(queryStr); 19 | futureBizData.setBizData(bizData); 20 | } 21 | }.start(); 22 | return futureBizData; 23 | } 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/future/simple/FutureBizData.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.future.simple; 2 | 3 | public class FutureBizData { 4 | //FutureData是RealData的包装 5 | protected BizData bizData = null; 6 | protected boolean isReady = false; 7 | 8 | public synchronized void setBizData(BizData bizData) { 9 | if (isReady) { 10 | return; 11 | } 12 | this.bizData = bizData; 13 | isReady = true; 14 | notifyAll();//RealData已经被注入,通知getResult() 15 | } 16 | 17 | public synchronized String getResult() {//会等待RealData构造完成 18 | while (!isReady) { 19 | try { 20 | wait();//一直等待,直到RealData被注入 21 | } catch (InterruptedException e) { 22 | e.printStackTrace(); 23 | } 24 | } 25 | return bizData.getResult(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/interrupt/InterruptCheck.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.interrupt; 2 | 3 | /** 4 | * 可以在 Thread 对象上调用 isInterrupted()方法来检查任何线程的中断状态。这里需要注意:线程一旦被中断, 5 | * isInterrupted()方法便会返回 true,而一旦 sleep()方法抛出异常,它将清空中断标志,此时isInterrupted()方法将返回 false。 6 | * User : krisjin 7 | * Date: 2015/9/8 8 | */ 9 | public class InterruptCheck { 10 | 11 | public static void main(String[] args) { 12 | Thread thread = Thread.currentThread(); 13 | 14 | System.out.println("1- thread isInterrupted() : " + thread.isInterrupted()); 15 | Double.parseDouble("12121"); 16 | //待决中断,中断自身 17 | thread.interrupt(); 18 | System.out.println("2- thread isInterrupted() : " + thread.isInterrupted()); 19 | System.out.println("3- thread isInterrupted() : " + thread.isInterrupted()); 20 | 21 | try { 22 | Thread.sleep(2000); 23 | System.out.println("thread is not interrupted"); 24 | } catch (InterruptedException e) { 25 | System.out.println("thread is interrupted : "); 26 | } 27 | 28 | //抛出异常后,会清除中断标志,这里会返回false 29 | System.out.println("4- thread isInterrupted() : " + thread.isInterrupted()); 30 | } 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/interrupt/InterruptReset.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.interrupt; 2 | 3 | /** 4 | * 测试当前线程是否已经中断。线程的中断状态 由该方法清除。换句话说,如果连续两次调用该方法, 5 | * 则第二次调用将返回 false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前, 6 | * 当前线程再次中断的情况除外)。线程中断被忽略,因为在中断时不处于活动状态的线程将由此返回 false 的方法反映出来。 7 | *

8 | * User : krisjin 9 | * Date: 2015/9/8 10 | */ 11 | public class InterruptReset { 12 | 13 | public static void main(String[] args) { 14 | System.out.println("Point X: Thread.interrupted()=" + Thread.interrupted()); 15 | 16 | Thread.currentThread().interrupt(); 17 | 18 | System.out.println("Point Y: Thread.interrupted()=" + Thread.interrupted()); 19 | 20 | try { 21 | Thread.sleep(1000); 22 | } catch (InterruptedException e) { 23 | e.printStackTrace(); 24 | } 25 | 26 | System.out.println("Point Z: Thread.interrupted()=" + Thread.interrupted()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/interrupt/PendingInterrupt.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.interrupt; 2 | 3 | /** 4 | * main 线程中断它自身。除了将中断标志(它是 Thread 的内部标志)设置为 true 外,没有其他任何影响。线程被中断了,但 main 线程仍然运行, 5 | * main 线程继续监视实时时钟,并进入 try 块,一旦调用 sleep()方法, 6 | * 它就会注意到待决中断的存在,并抛出 InterruptException。于是执行跳转到 catch 块, 7 | * 并打印出线程被中断的信息。最后,计算并打印出时间差。 8 | *

9 | * User : krisjin 10 | * Date: 2015/9/8 11 | */ 12 | public class PendingInterrupt { 13 | 14 | public static void main(String[] args) { 15 | 16 | //是否执行线程终端操作 17 | boolean isInterrupt = false; 18 | 19 | if (isInterrupt) { 20 | Thread.currentThread().interrupt(); 21 | //在执行中断操作并return;,后面的操作将不会执行 22 | // return; 23 | } 24 | 25 | long startTime = System.currentTimeMillis(); 26 | try { 27 | Thread.sleep(10000); 28 | System.out.println("current thread is not interrupt"); 29 | } catch (InterruptedException e) { 30 | System.out.println("current thread is interrupt"); 31 | } 32 | 33 | long endTime = System.currentTimeMillis(); 34 | System.out.println("interrupt is " + isInterrupt + "; cost:" + (endTime - startTime)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/interrupt/SleepInterrupt.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.interrupt; 2 | 3 | /** 4 | * User : krisjin 5 | * Date: 2015/9/8 6 | */ 7 | public class SleepInterrupt implements Runnable { 8 | 9 | public static void main(String[] args) { 10 | SleepInterrupt sleepInterrupt = new SleepInterrupt(); 11 | Thread threadA = new Thread(sleepInterrupt); 12 | threadA.start(); 13 | 14 | try { 15 | Thread.sleep(4000); 16 | } catch (InterruptedException e) { 17 | e.printStackTrace(); 18 | } 19 | 20 | System.out.println("main() - interrupting other thread"); 21 | threadA.interrupt(); 22 | System.out.println("main() - end"); 23 | } 24 | 25 | @Override 26 | public void run() { 27 | try { 28 | System.out.println("run() sleep 10 seconds"); 29 | Thread.sleep(10000); 30 | } catch (InterruptedException e) { 31 | System.out.println("run() - interrupted while sleeping"); 32 | //处理完中断异常后,返回到run()方法人口,.如果没有return,线程不会实际被中断,它会继续打印下面的信息 33 | return; 34 | } 35 | System.out.println("run() - leaving normally"); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/jol/JolExample.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.jol; 2 | 3 | import org.openjdk.jol.info.ClassLayout; 4 | import org.openjdk.jol.vm.VM; 5 | 6 | import static java.lang.System.out; 7 | 8 | /** 9 | * -XX:-UseCompressedOops 10 | * @author kris 11 | * @date 2023/1/16 12 | */ 13 | public class JolExample { 14 | 15 | public static void main(String[] args) { 16 | User user = new User(); 17 | out.println(VM.current().details()); 18 | out.println(ClassLayout.parseInstance(user).toPrintable()); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/jol/User.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.jol; 2 | 3 | /** 4 | * @author kris 5 | * @date 2023/1/16 6 | */ 7 | public class User { 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/jvm/CmsGcLogTest.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.jvm; 2 | 3 | /** 4 | * -Xms22528m -Xmx22528m -XX:MaxMetaspaceSize=256m -XX:MetaspaceSize=256m -XX:MaxDirectMemorySize=2048m -Xss512K -Djava.library.path=/usr/local/lib -server -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationConcurrentTime -XX:+PrintHeapAtGC -Xloggc:/export/log/gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/Logs -Djava.awt.headless=true -Dsun.net.client.defaultConnectTimeout=60000 5 | * -Xms20m -Xmx20m -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseConcMarkSweepGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/tool/training/log/cms.log 6 | * -XX:+CMSScavengeBeforeRemark 7 | */ 8 | public class CmsGcLogTest { 9 | 10 | public static final int _1MB = 1024 * 1024; 11 | 12 | public static void main(String[] args) throws InterruptedException { 13 | int _1MB = 1024 * 1024; 14 | byte[] b1 = new byte[4 * _1MB]; 15 | byte[] b2 = new byte[4 * _1MB]; 16 | byte[] b3 = new byte[4 * _1MB]; 17 | byte[] b4 = new byte[4 * _1MB]; 18 | 19 | // Thread.sleep(2000); 20 | b4 = null; 21 | // byte[] b5 = new byte[4 * _1MB]; 22 | // byte[] b6 = new byte[4 * _1MB]; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/jvm/CpuHighLoadTest.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.jvm; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | 6 | /** 7 | * arthas 8 | */ 9 | public class CpuHighLoadTest { 10 | 11 | private static ExecutorService executorService = Executors.newFixedThreadPool(5); 12 | public static Object lock = new Object(); 13 | 14 | public static void main(String[] args) { 15 | Task task = new Task(); 16 | executorService.execute(task); 17 | } 18 | 19 | static class Task implements Runnable { 20 | long sum = 0L; 21 | 22 | public void run() { 23 | synchronized (lock) { 24 | while (true) { 25 | sum += 1; 26 | } 27 | } 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/jvm/DeathLockTest.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.jvm; 2 | 3 | import java.util.concurrent.locks.Lock; 4 | import java.util.concurrent.locks.ReentrantLock; 5 | 6 | /** 7 | * @author kris 8 | * @date 2023/9/1 9 | */ 10 | public class DeathLockTest { 11 | private static Lock lock1 = new ReentrantLock(); 12 | private static Lock lock2 = new ReentrantLock(); 13 | 14 | public static void main(String[] args) { 15 | deathLock(); 16 | } 17 | 18 | public static void deathLock() { 19 | Thread t1 = new Thread() { 20 | public void run() { 21 | try { 22 | lock1.lock(); 23 | System.out.println(Thread.currentThread().getName() + " get the lock1"); 24 | Thread.sleep(1000); 25 | lock2.lock(); 26 | System.out.println(Thread.currentThread().getName() + " get the lock2"); 27 | } catch (InterruptedException e) { 28 | e.printStackTrace(); 29 | } 30 | } 31 | }; 32 | Thread t2 = new Thread() { 33 | public void run() { 34 | try { 35 | lock2.lock(); 36 | System.out.println(Thread.currentThread().getName() + " get the lock2"); 37 | Thread.sleep(1000); 38 | lock1.lock(); 39 | System.out.println(Thread.currentThread().getName() + " get the lock1"); 40 | } catch (InterruptedException e) { 41 | e.printStackTrace(); 42 | } 43 | } 44 | }; 45 | t1.setName("readData"); 46 | t2.setName("writeData"); 47 | t1.start(); 48 | t2.start(); 49 | } 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/jvm/OutOfMemoryTest.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.jvm; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/tool/training/log/oom.hprof 8 | */ 9 | public class OutOfMemoryTest { 10 | public static final int _1MB = 1024 * 1024; 11 | 12 | public static void main(String[] args) { 13 | // byte[] b1 = new byte[4 * _1MB]; 14 | // Map map = new HashMap(); 15 | // int count = 1; 16 | // while (true) { 17 | // map.put(count, b1); 18 | // count++; 19 | // } 20 | // 21 | 22 | 23 | // 24 | // languageTemplateValue = MultiLangUtil.getLanguageTemplateValueMap( 25 | // IMeetingConstant.MeetingDialupCallAppPushEnum.MEETING_DIALUP_CALL_APP_PUSH_ENUM.getCorpusId(), 26 | // meetingInfo.getMeetingTitle().substring(0,meetingInfo.getMeetingTitle(). 27 | // indexOf(IMeetingConstant.QUICK_MEETING_TITLESUBSTRING_STR))); 28 | 29 | String s = "abc"; 30 | 31 | } 32 | 33 | 34 | 35 | 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/jvm/TestStackDeep.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.jvm; 2 | 3 | /** 4 | * 递归调用 5 | *

 6 |  * -Xss128K
 7 |  * deep of calling = 701
 8 |  * java.lang.StackOverflowError
 9 |  *
10 |  * -Xss256K
11 |  * deep of calling = 1817
12 |  * java.lang.StackOverflowError
13 |  *
14 |  * -Xss
15 |  * 通常只有几百K
16 |  * 决定了函数调用的深度
17 |  * 每个线程都有独立的栈空间
18 |  * 局部变量、参数 分配在栈上
19 |  *
20 |  * 如果堆空间没有用完也抛出了OOM,有可能是永久区导致的
21 |  *
22 |  * Xmx20m -Xms5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/a.dump
23 |  *
24 |  *
25 |  * -Xmn
26 |  *      设置新生代大小
27 |  * -XX:NewRatio
28 |  *      新生代(eden+2*s)和老年代(不包含永久区)的比值
29 |  *      4 表示 新生代:老年代=1:4,即年轻代占堆的1/5
30 |  * -XX:SurvivorRatio
31 |  *      设置两个Survivor区和eden的比
32 |  *      8表示 两个Survivor :eden=2:8,即一个Survivor占年轻代的1/10
33 |  *
34 |  * 
35 | */ 36 | public class TestStackDeep { 37 | 38 | private static int count = 0; 39 | 40 | public static void recursion(long a, long b, long c) { 41 | long e = 1, f = 2, g = 3, h = 4, i = 5, k = 6, q = 7, x = 8, y = 9, z = 10; 42 | count++; 43 | recursion(a, b, c); 44 | } 45 | 46 | public static void main(String args[]) { 47 | try { 48 | recursion(0L, 0L, 0L); 49 | 50 | 51 | } catch (Throwable e) { 52 | System.out.println("deep of calling = " + count); 53 | e.printStackTrace(); 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lambda/Interface1.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lambda; 2 | 3 | public class Interface1 { 4 | 5 | interface Formula { 6 | double calculate(int a); 7 | 8 | default double sqrt(int a) { 9 | return Math.sqrt(positive(a)); 10 | } 11 | 12 | static int positive(int a) { 13 | return a > 0 ? a : 0; 14 | } 15 | } 16 | 17 | public static void main(String[] args) { 18 | Formula formula1 = new Formula() { 19 | public double calculate(int a) { 20 | return sqrt(a * 100); 21 | } 22 | }; 23 | 24 | double v1 = formula1.calculate(10); 25 | formula1.sqrt(-23); 26 | Formula.positive(-4); 27 | System.err.println(v1); 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lambda/Sort1.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lambda; 2 | 3 | import java.util.*; 4 | 5 | public class Sort1 { 6 | public static void main(String[] args) { 7 | List names = Arrays.asList("peter", "anna", "mike", "xenia"); 8 | 9 | Collections.sort(names, new Comparator() { 10 | @Override 11 | public int compare(String a, String b) { 12 | return b.compareTo(a); 13 | } 14 | }); 15 | 16 | Collections.sort(names, (String a, String b) -> { 17 | return b.compareTo(a); 18 | }); 19 | 20 | Collections.sort(names, (String a, String b) -> b.compareTo(a)); 21 | 22 | Collections.sort(names, (a, b) -> a.compareTo(b)); 23 | 24 | System.out.println(names); 25 | 26 | names.sort(Collections.reverseOrder()); 27 | 28 | System.out.println(names); 29 | 30 | List names2 = Arrays.asList("peter", null, "anna", "mike", "xenia"); 31 | names2.sort(Comparator.nullsLast(String::compareTo)); 32 | System.out.println(names2); 33 | 34 | List names3 = null; 35 | 36 | Optional.ofNullable(names3).ifPresent(list -> list.sort(Comparator.naturalOrder())); 37 | 38 | System.out.println(names3); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/BasicObjectLockTest.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lock; 2 | 3 | /** 4 | * 轻量级锁 5 | *
 6 |  * 嵌入在线程栈中的对象
 7 |  *
 8 |  * 普通的锁处理性能不够理想,轻量级锁是一种快速的锁定方法。
 9 |  * 如果对象没有被锁定
10 |  * 将对象头的Mark指针保存到锁对象中
11 |  * 将对象头设置为指向锁的指针(在线程栈空间中)
12 |  *
13 |  * 如果轻量级锁失败,表示存在竞争,升级为重量级锁(常规锁)
14 |  * 在没有锁竞争的前提下,减少传统锁使用OS互斥量产生的性能损耗
15 |  * 在竞争激烈时,轻量级锁会多做很多额外操作,导致性能下降
16 |  * 
17 | * 18 | * @author krisjin on 2019/4/26 19 | */ 20 | public class BasicObjectLockTest { 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/BiasedLock.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lock; 2 | 3 | import java.util.List; 4 | import java.util.Vector; 5 | 6 | /** 7 | * -XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0 8 | * -XX:-UseBiasedLocking 9 | *
10 |  * 大部分情况是没有竞争的,所以可以通过偏向来提高性能
11 |  * 所谓的偏向,就是偏心,即锁会偏向于当前已经占有锁的线程
12 |  * 将对象头Mark的标记设置为偏向,并将线程ID写入对象头Mark
13 |  * 只要没有竞争,获得偏向锁的线程,在将来进入同步块,不需要做同步
14 |  * 当其他线程请求相同的锁时,偏向模式结束
15 |  * -XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0
16 |  * -XX:+UseBiasedLocking
17 |  * 默认启用
18 |  * 在竞争激烈的场合,偏向锁会增加系统负担
19 |  * 
20 | * 21 | * @author krisjin on 2019/4/26 22 | */ 23 | public class BiasedLock { 24 | public static List numberList = new Vector<>(); 25 | 26 | public static void main(String[] args) throws InterruptedException { 27 | long begin = System.currentTimeMillis(); 28 | int count = 0; 29 | int startNum = 0; 30 | while (count < 10000000) { 31 | numberList.add(startNum); 32 | startNum += 2; 33 | count++; 34 | } 35 | long end = System.currentTimeMillis(); 36 | System.out.println(end - begin); 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/BoundedHashSet.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lock; 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 | * 使用Semaphore为容器设置边界 10 | *

11 | * 12 | * @User : krisjin 13 | * @Date: 2015/9/15 14 | */ 15 | public class BoundedHashSet { 16 | private final Set set; 17 | private final Semaphore semaphore; 18 | 19 | public BoundedHashSet(int bound) { 20 | this.set = Collections.synchronizedSet(new HashSet()); 21 | this.semaphore = new Semaphore(bound); 22 | } 23 | 24 | public boolean add(T o) throws InterruptedException { 25 | boolean result = false; 26 | try { 27 | semaphore.acquire(); 28 | result = set.add(o); 29 | return result; 30 | } finally { 31 | if (!result) { 32 | semaphore.release(); 33 | } 34 | } 35 | } 36 | 37 | public boolean remove(T o) { 38 | boolean result = set.remove(o); 39 | if (result) { 40 | semaphore.release(); 41 | } 42 | return result; 43 | } 44 | 45 | public static void main(String[] args) { 46 | int i = 1; 47 | while (true) { 48 | if (i % 100 == 0) { 49 | try { 50 | Thread.sleep(1000); 51 | } catch (InterruptedException e) { 52 | e.printStackTrace(); 53 | } 54 | } 55 | i++; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/CountDownLatchDemo.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lock; 2 | 3 | import java.util.concurrent.CountDownLatch; 4 | 5 | /** 6 | * 该类主要用于并发同步操作,如果是串行好像用不上这个,子任务执行countDown减一,指导count==0 7 | * 接着继续执行主线程 8 | * 倒计时锁存器的同步控制。 9 | * 使用AQS状态表示计数 10 | * CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能。比如有一个任务A, 11 | * 它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。 12 | *

13 | * CountDownLatch类只提供了一个构造器: 14 | * 15 | * @author krisjin 16 | * @date 2020/11/19 17 | */ 18 | public class CountDownLatchDemo { 19 | 20 | public static void main(String[] args) { 21 | demo1(); 22 | } 23 | 24 | public static void demo1() { 25 | //创建一个控制线程间等待的 thread count down latch 26 | CountDownLatch countDownLatch = new CountDownLatch(2); 27 | 28 | Thread t1 = new Thread(new Runnable() { 29 | @Override 30 | public void run() { 31 | System.err.println("t1 done..."); 32 | countDownLatch.countDown(); 33 | } 34 | }); 35 | 36 | Thread t2 = new Thread(new Runnable() { 37 | @Override 38 | public void run() { 39 | System.err.println("t2 done..."); 40 | countDownLatch.countDown(); 41 | } 42 | }); 43 | 44 | t1.start(); 45 | t2.start(); 46 | 47 | try { 48 | countDownLatch.await(); 49 | } catch (InterruptedException e) { 50 | e.printStackTrace(); 51 | } 52 | System.err.println("main done..."); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/DeadLockAvoid.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lock; 2 | 3 | /** 4 | *

 5 |  * 在有些情况下死锁是可以避免的,介绍三种用于避免死锁的技术:
 6 |  * 1.加锁顺序
 7 |  * 2.加锁时限
 8 |  * 3.死锁检测
 9 |  *
10 |  * 加锁顺序:
11 |  * 当多个线程需要相同的一些锁,但是按照不同的顺序加锁,死锁就很容易发生。
12 |  * 如果能确保所有的线程都是按照相同的顺序获得锁,那么死锁就不会发生。看下面这个例子:
13 |  * Thread 1: lock Demo1Main lock B
14 |  * Thread 2: wait for Demo1Main  ,lock C(获取A锁后,才能继续获取C锁)
15 |  * Thread 3: wait for Demo1Main ,wait for B , wait for C
16 |  * 如果一个线程(比如线程3获取锁),那么它必须按照确定的顺序获取锁
17 |  * 
18 | * User: krisjin 19 | * Date: 2016/1/26 20 | */ 21 | public class DeadLockAvoid { 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/LazyInitSingleton.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lock; 2 | 3 | /** 4 | * User:krisjin 5 | * Date:2020-05-08 6 | */ 7 | public class LazyInitSingleton { 8 | private volatile static LazyInitSingleton instance = null; 9 | 10 | private LazyInitSingleton() { 11 | } 12 | 13 | public static LazyInitSingleton getInstance() { 14 | if (instance == null) { 15 | synchronized (LazyInitSingleton.class) { 16 | if (instance == null) { 17 | instance = new LazyInitSingleton(); 18 | } 19 | } 20 | } 21 | return instance; 22 | } 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/LockSupportDemo.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lock; 2 | 3 | import java.util.Queue; 4 | import java.util.concurrent.ConcurrentLinkedQueue; 5 | import java.util.concurrent.atomic.AtomicBoolean; 6 | import java.util.concurrent.locks.LockSupport; 7 | 8 | public class LockSupportDemo { 9 | 10 | 11 | public static void main(String[] args) { 12 | test1(); 13 | } 14 | 15 | 16 | public static void test1() { 17 | System.out.println("park"); 18 | LockSupport.park(); 19 | LockSupport.unpark(Thread.currentThread()); 20 | System.out.println("end park"); 21 | } 22 | 23 | 24 | class FIFOMutex { 25 | private final AtomicBoolean locked = new AtomicBoolean(false); 26 | private final Queue waiters = new ConcurrentLinkedQueue(); 27 | 28 | public void lock() { 29 | boolean wasInterrupted = false; 30 | Thread current = Thread.currentThread(); 31 | waiters.add(current); 32 | 33 | // Block while not first in queue or cannot acquire lock 34 | while (waiters.peek() != current || 35 | !locked.compareAndSet(false, true)) { 36 | LockSupport.park(this); 37 | if (Thread.interrupted()) // ignore interrupts while waiting 38 | wasInterrupted = true; 39 | } 40 | 41 | waiters.remove(); 42 | if (wasInterrupted) // reassert interrupt status on exit 43 | current.interrupt(); 44 | } 45 | 46 | public void unlock() { 47 | locked.set(false); 48 | LockSupport.unpark(waiters.peek()); 49 | } 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/SemaphoreDemo.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lock; 2 | 3 | import java.util.Date; 4 | import java.util.concurrent.ExecutorService; 5 | import java.util.concurrent.Executors; 6 | import java.util.concurrent.Semaphore; 7 | import java.util.concurrent.TimeUnit; 8 | 9 | public class SemaphoreDemo { 10 | /** 11 | * 最大每秒查询率 12 | */ 13 | final static int MAX_QPS = 1000; 14 | /** 15 | * 信号量 16 | */ 17 | final static Semaphore semaphore = new Semaphore(MAX_QPS); 18 | 19 | public static void main(String... args) throws Exception { 20 | //创建调度线程池 21 | Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() { 22 | public void run() { 23 | semaphore.release(MAX_QPS / 2); 24 | } 25 | 26 | }, 1000, 500, TimeUnit.MILLISECONDS); 27 | //lots of concurrent calls:100 * 1000 28 | 29 | //创建固定大小线程池 30 | ExecutorService pool = Executors.newFixedThreadPool(100); 31 | 32 | for (int i = 100; i > 0; i--) { 33 | final int x = i; 34 | pool.submit(new Runnable() { 35 | public void run() { 36 | for (int j = 1000; j > 0; j--) { 37 | semaphore.acquireUninterruptibly(1); 38 | remoteCall(x, j); 39 | } 40 | } 41 | }); 42 | } 43 | pool.shutdown(); 44 | pool.awaitTermination(1, TimeUnit.HOURS); 45 | System.out.println("DONE"); 46 | } 47 | 48 | private static void remoteCall(int i, int j) { 49 | System.out.println(String.format("%s - %s: %d %d", new Date(), Thread.currentThread(), i, j)); 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/SeparationLock.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lock; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.concurrent.locks.ReentrantReadWriteLock; 6 | 7 | /** 8 | * 分离锁,使用{@link ReentrantReadWriteLock} 9 | *

10 | * User : krisjin 11 | * Date: 2015/9/14 12 | * Time: 9:29 13 | */ 14 | public class SeparationLock { 15 | 16 | private final Map[] maps = null; 17 | private final ReentrantReadWriteLock[] lock = null; 18 | private int seg = 16; 19 | 20 | public SeparationLock(int seg) { 21 | this.seg = seg; 22 | init(); 23 | } 24 | 25 | public SeparationLock() { 26 | init(); 27 | } 28 | 29 | 30 | private int hashKey(Object key) { 31 | return key.hashCode() % seg; 32 | } 33 | 34 | 35 | /** 36 | * 初始化 37 | */ 38 | private void init() { 39 | for (int i = 0; i < seg; i++) { 40 | maps[i] = new HashMap(); 41 | lock[i] = new ReentrantReadWriteLock(); 42 | } 43 | } 44 | 45 | /** 46 | * @param key 47 | * @param value 48 | */ 49 | public void put(Object key, Object value) { 50 | int i = hashKey(key); 51 | lock[i].writeLock().lock(); 52 | try { 53 | maps[i].put(key, value); 54 | } finally { 55 | lock[i].writeLock().unlock(); 56 | } 57 | } 58 | 59 | public Object get(Object key) { 60 | int i = hashKey(key); 61 | Object value = null; 62 | lock[i].readLock().lock(); 63 | try { 64 | value = maps[i].get(key); 65 | } finally { 66 | lock[i].readLock().unlock(); 67 | } 68 | return value; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/SimpleLock.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lock; 2 | 3 | /** 4 | * User:krisjin 5 | * Date:2019/4/26 6 | */ 7 | public class SimpleLock { 8 | private boolean isLocked = false; 9 | 10 | public synchronized void lock() throws InterruptedException { 11 | while (isLocked) { 12 | wait(); 13 | } 14 | isLocked = true; 15 | 16 | } 17 | 18 | public synchronized void unlock() { 19 | isLocked = false; 20 | notify(); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/SimpleLockCount.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lock; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * User:krisjin 8 | * Date:2019/4/26 9 | */ 10 | public class SimpleLockCount { 11 | 12 | 13 | public static void main(String[] args) throws InterruptedException { 14 | List data = new ArrayList(); 15 | SimpleLock lock = new SimpleLock(); 16 | 17 | Thread t1 = new Thread(new CountTask(lock, data)); 18 | t1.setName("A"); 19 | Thread t2 = new Thread(new CountTask(lock, data)); 20 | t2.setName("B"); 21 | 22 | t1.start(); 23 | t2.start(); 24 | t1.join(); 25 | t2.join(); 26 | 27 | System.out.println(data.size()); 28 | 29 | } 30 | 31 | 32 | public static class CountTask implements Runnable { 33 | SimpleLock simpleLock; 34 | List data; 35 | 36 | 37 | public CountTask(SimpleLock simpleLock, List data) { 38 | this.simpleLock = simpleLock; 39 | this.data = data; 40 | } 41 | 42 | @Override 43 | public void run() { 44 | try { 45 | simpleLock.lock(); 46 | for (int i = 0; i < 10; i++) { 47 | data.add(i); 48 | 49 | System.out.println(Thread.currentThread().getName() + " add..." + i); 50 | } 51 | 52 | simpleLock.unlock(); 53 | } catch (InterruptedException e) { 54 | e.printStackTrace(); 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/SpinLock.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lock; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.ArrayList; 5 | import java.util.Calendar; 6 | import java.util.List; 7 | 8 | /** 9 | *

10 |  * 当竞争存在时,如果线程可以很快获得锁,那么可以不在OS层挂起线程,让线程做几个空操作(自旋)
11 |  * JDK1.6中-XX:+UseSpinning开启
12 |  * JDK1.7中,去掉此参数,改为内置实现
13 |  * 如果同步块很长,自旋失败,会降低系统性能
14 |  * 如果同步块很短,自旋成功,节省线程挂起切换时间,提升系统性能
15 |  * 
16 | * 17 | * @author krisjin on 2019/4/26 18 | */ 19 | public class SpinLock { 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/TimeConsumingLock.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lock; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * synchronized同步作用域的大小,对性能有影响。 8 | */ 9 | public class TimeConsumingLock implements Runnable { 10 | 11 | private final Map map = new HashMap(); 12 | 13 | private volatile int flag = 1; 14 | 15 | public TimeConsumingLock(int flag) { 16 | this.flag = flag; 17 | } 18 | 19 | public static void main(String[] args) { 20 | TimeConsumingLock timeConsumingLock = new TimeConsumingLock(5000000); 21 | Thread thread = new Thread(timeConsumingLock); 22 | long startTime = System.currentTimeMillis(); 23 | 24 | thread.start(); 25 | try { 26 | thread.join(); 27 | } catch (InterruptedException e) { 28 | e.printStackTrace(); 29 | } 30 | long costTime = System.currentTimeMillis() - startTime; 31 | System.out.println(costTime); 32 | 33 | } 34 | 35 | public synchronized void write(Object key) { 36 | if (null == key) { 37 | return; 38 | } 39 | map.put(key, "value"); 40 | 41 | } 42 | 43 | public synchronized void write2(Object key) { 44 | if (null == key) { 45 | return; 46 | } 47 | synchronized (this) { 48 | map.put(key, "val"); 49 | } 50 | 51 | } 52 | 53 | @Override 54 | public void run() { 55 | for (int i = 0; i < flag; i++) { 56 | // write(i); 57 | write2(i); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/lock.md: -------------------------------------------------------------------------------- 1 | 偏向锁,轻量级锁,自旋锁总结 2 | 3 | 4 | 5 | 不是Java语言层面的锁优化方法 6 | 内置于JVM中的获取锁的优化方法和获取锁的步骤 7 | 偏向锁可用会先尝试偏向锁 8 | 轻量级锁可用会先尝试轻量级锁 9 | 以上都失败,尝试自旋锁 10 | 再失败,尝试普通锁,使用OS互斥量在操作系统层挂起 11 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/reentrant/Demo1Main.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lock.reentrant; 2 | 3 | /** 4 | * @author krisjin 5 | */ 6 | public class Demo1Main { 7 | 8 | /** 9 | * 在当前执行的任务,每个任务现场都是顺序执行的 10 | * 共享对象,不同的线程调用各自的方法 11 | * 一个线程获取lock之后,其它的线程只能等待,直到锁被释放 12 | */ 13 | public static void main(String[] args) { 14 | Demo1Service service = new Demo1Service(); 15 | TaskService taskService = new TaskService(service); 16 | Thread thread1 = new Thread(taskService); 17 | Thread thread2 = new Thread(taskService); 18 | Thread thread3 = new Thread(new Runnable() { 19 | @Override 20 | public void run() { 21 | service.methodB(); 22 | } 23 | }); 24 | thread1.start(); 25 | thread3.start(); 26 | thread2.start(); 27 | } 28 | 29 | 30 | protected static class TaskService implements Runnable { 31 | 32 | private Demo1Service demo1Service; 33 | 34 | public TaskService(Demo1Service demo1Service) { 35 | this.demo1Service = demo1Service; 36 | } 37 | 38 | @Override 39 | public void run() { 40 | demo1Service.methodA(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/reentrant/Demo1Service.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lock.reentrant; 2 | 3 | import java.util.concurrent.locks.Lock; 4 | import java.util.concurrent.locks.ReentrantLock; 5 | 6 | public class Demo1Service { 7 | private Lock lock = new ReentrantLock(); 8 | 9 | public void methodA() { 10 | lock.lock(); 11 | for (int i = 0; i < 5; i++) { 12 | System.out.println("ThreadName=" + Thread.currentThread().getName() + " A method:" + (i + 1)); 13 | } 14 | lock.unlock(); 15 | } 16 | 17 | public void methodB() { 18 | lock.lock(); 19 | for (int i = 0; i < 5; i++) { 20 | System.out.println("ThreadName=" + Thread.currentThread().getName() + " B method:" + (i + 1)); 21 | } 22 | lock.unlock(); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/reentrant/SynReentrantDemo.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.lock.reentrant; 2 | 3 | /** 4 | * 该类中声名了两个同步方法methodA 和 methodB, 5 | * User:krisjin 6 | * Date:2019/4/26 7 | */ 8 | public class SynReentrantDemo { 9 | public synchronized void methodA() { 10 | System.out.println("methodA..."); 11 | methodB(); 12 | 13 | } 14 | 15 | public synchronized void methodB() { 16 | System.out.println("methodB..."); 17 | } 18 | 19 | public static void main(String[] args) { 20 | new Thread(new Runnable() { 21 | SynReentrantDemo synReentrantDemo = new SynReentrantDemo(); 22 | 23 | @Override 24 | public void run() { 25 | synReentrantDemo.methodA(); 26 | } 27 | }).start(); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/lock/reentrant/reentrant.md: -------------------------------------------------------------------------------- 1 | 使用synchronized可以实现线程间的同步互斥,JUC中的ReentrantLock类也能达到相同的效果,并且在 2 | 扩展功能上也更加强大,比如具有嗅探锁定,多路分支通知等功能,而且在使用上比synchronized更加灵活 3 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/masterworker/PlusWorker.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.masterworker; 2 | 3 | /** 4 | * @author krisjin on 2017/5/13 5 | */ 6 | public class PlusWorker extends Worker { 7 | 8 | /** 9 | * cubic sum 10 | * 11 | * @param input 12 | * @return 13 | */ 14 | @Override 15 | public Object handle(Object input) { 16 | Integer i = (Integer) input; 17 | 18 | return i * i * i; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/masterworker/Test.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.masterworker; 2 | 3 | import java.util.Map; 4 | import java.util.Set; 5 | 6 | /** 7 | * @author krisjin on 2017/5/13 8 | */ 9 | public class Test { 10 | 11 | public static void main(String[] args) { 12 | System.out.println("start..."); 13 | Long st = System.currentTimeMillis(); 14 | Master m = new Master(new PlusWorker(), 5); 15 | 16 | for (int i = 0; i < 100; i++) { 17 | m.submit(i); 18 | } 19 | m.execute(); 20 | int re = 0; 21 | Map resultMap = m.getResultMap(); 22 | 23 | while (resultMap.size() > 0 || !m.isComplete()) { 24 | Set keys = resultMap.keySet(); 25 | String key = null; 26 | for (String k : keys) { 27 | key = k; 28 | break; 29 | } 30 | Integer i = null; 31 | if (key != null) { 32 | i = (Integer) resultMap.get(key); 33 | } 34 | 35 | if (i != null) 36 | re += i; 37 | 38 | if (key != null) 39 | resultMap.remove(key); 40 | } 41 | 42 | System.out.println("最终计算结果=" + re + " ;cost time:" + (System.currentTimeMillis() - st) + "ms"); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/masterworker/Worker.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.masterworker; 2 | 3 | import java.util.Map; 4 | import java.util.Queue; 5 | 6 | /** 7 | * Worker进程 8 | * 9 | * @author krisjin on 2017/5/13 10 | */ 11 | public class Worker implements Runnable { 12 | 13 | //任务队列,用于取得子任务 14 | protected Queue workQueue; 15 | 16 | //子任务处理结果集 17 | protected Map resultMap; 18 | 19 | 20 | public void setWorkQueue(Queue workQueue) { 21 | this.workQueue = workQueue; 22 | } 23 | 24 | public void setResultMap(Map resultMap) { 25 | this.resultMap = resultMap; 26 | } 27 | 28 | public Object handle(Object input) { 29 | return input; 30 | } 31 | 32 | @Override 33 | public void run() { 34 | while (true) { 35 | Object input = workQueue.poll(); 36 | if (input == null) break; 37 | Object result = handle(input); 38 | resultMap.put(Integer.toString(input.hashCode()), result); 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/model/KeyListener.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.model; 2 | 3 | /** 4 | * User : krisjin 5 | * Date: 2015/9/9 6 | */ 7 | public class KeyListener { 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/model/MouseListener.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.model; 2 | 3 | /** 4 | * User : krisjin 5 | * Date: 2015/9/9 6 | */ 7 | public class MouseListener { 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/model/Point.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.model; 2 | 3 | /** 4 | * 不可变的Point类,所以是线程安全的。 5 | */ 6 | public class Point { 7 | 8 | public final int x; 9 | public final int y; 10 | 11 | public Point(int x, int y) { 12 | this.x = x; 13 | this.y = y; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/model/xml/XMLSerializerTest.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.model.xml; 2 | 3 | import net.sf.json.xml.XMLSerializer; 4 | 5 | public class XMLSerializerTest { 6 | 7 | static String c = " \n" + 8 | "\n" + 9 | "243242\n" + 10 | "\n" + 11 | ""; 12 | 13 | 14 | public static void main(String[] args) { 15 | String newStr = new String(); 16 | String parseStr = "utf-8a"; 17 | int i = 0; 18 | if ((i = c.indexOf(parseStr)) != -1) { 19 | newStr = c.substring(i + 8).trim(); 20 | } 21 | System.err.println(toJSONString(newStr)); 22 | } 23 | 24 | public static String toJSONString(String xml) { 25 | XMLSerializer xmlSerializer = new XMLSerializer(); 26 | String resutStr = xmlSerializer.read(xml).toString(); //0表示去除换行空格等,1以上表示json格式化后的数据 27 | return resutStr; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/objectshare/NoVisibility.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.objectshare; 2 | 3 | /** 4 | * 存在可变的共享变量,非线程安全类。 5 | */ 6 | public class NoVisibility { 7 | private static boolean ready; 8 | private static int number; 9 | 10 | public static void main(String[] args) { 11 | new ReaderThread().start(); 12 | new ReaderThread().start(); 13 | ready = true; 14 | number = 31; 15 | } 16 | 17 | private static class ReaderThread extends Thread { 18 | @Override 19 | public void run() { 20 | while (!ready) { 21 | Thread.yield(); 22 | } 23 | System.out.println("read number : " + number); 24 | } 25 | } 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/objectshare/SafePublish.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.objectshare; 2 | 3 | /** 4 | * 1.不要在构造函数中使用this应用逸出 5 | * 2.使用工程方法来防止this引用在构造函数中逸出 6 | * User : krisjin 7 | * Date: 2015/9/8 8 | */ 9 | public class SafePublish { 10 | 11 | private final Publish publish; 12 | 13 | private SafePublish() { 14 | publish = new Publish(); 15 | } 16 | 17 | public static SafePublish newInstance() { 18 | SafePublish safePublish = new SafePublish(); 19 | return safePublish; 20 | } 21 | } 22 | 23 | 24 | class Publish { 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/producerconsumer/ClientMain.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.producerconsumer; 2 | 3 | import java.util.concurrent.BlockingDeque; 4 | import java.util.concurrent.ExecutorService; 5 | import java.util.concurrent.Executors; 6 | import java.util.concurrent.LinkedBlockingDeque; 7 | 8 | /** 9 | * @author krisjin on 2017/5/17 10 | */ 11 | public class ClientMain { 12 | 13 | public static void main(String[] args) throws InterruptedException { 14 | BlockingDeque queue = MessageQueue.get(); 15 | ExecutorService executorService = Executors.newCachedThreadPool(); 16 | 17 | Producer producer = new Producer(queue); 18 | Consumer consumer = new Consumer(queue); 19 | 20 | executorService.execute(producer); 21 | executorService.execute(consumer); 22 | 23 | Thread.sleep(1000); 24 | producer.stop(); 25 | consumer.stop(); 26 | 27 | 28 | executorService.shutdownNow(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/producerconsumer/Consumer.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.producerconsumer; 2 | 3 | import java.util.Random; 4 | import java.util.concurrent.BlockingQueue; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | /** 8 | * @author krisjin on 2017/5/17 9 | */ 10 | public class Consumer implements Runnable { 11 | private BlockingQueue queue; 12 | private volatile boolean isRunning = true; 13 | 14 | public Consumer(BlockingQueue queue) { 15 | this.queue = queue; 16 | } 17 | 18 | public void run() { 19 | Random r = new Random(); 20 | System.out.println("consumer thread is start..."); 21 | 22 | try { 23 | if (isRunning) { 24 | String msg = (String) queue.poll(10, TimeUnit.MILLISECONDS); 25 | if (msg != null) { 26 | System.out.println("consumer data = " + msg); 27 | Thread.sleep(r.nextInt(1000)); 28 | } 29 | } 30 | } catch (InterruptedException e) { 31 | e.printStackTrace(); 32 | Thread.currentThread().interrupt(); 33 | } 34 | } 35 | 36 | public void stop() { 37 | isRunning = false; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/producerconsumer/MessageQueue.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.producerconsumer; 2 | 3 | import java.util.concurrent.BlockingDeque; 4 | import java.util.concurrent.LinkedBlockingDeque; 5 | 6 | /** 7 | * @author krisjin 8 | * @date 2020/10/29 9 | */ 10 | public class MessageQueue { 11 | 12 | private static BlockingDeque queue = new LinkedBlockingDeque<>(); 13 | 14 | public static BlockingDeque get() { 15 | return queue; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/producerconsumer/Producer.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.producerconsumer; 2 | 3 | import java.util.Date; 4 | import java.util.Random; 5 | import java.util.concurrent.BlockingDeque; 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | 8 | /** 9 | * @author krisjin on 2017/5/17 10 | */ 11 | public class Producer implements Runnable { 12 | private volatile boolean isRunning = true; 13 | private BlockingDeque queue; 14 | private AtomicInteger count = new AtomicInteger(); 15 | 16 | public Producer(BlockingDeque queue) { 17 | this.queue = queue; 18 | } 19 | 20 | public void run() { 21 | Random random = new Random(); 22 | System.out.println("producer thread is start..."); 23 | try { 24 | while (isRunning) 25 | for (int i = 0; i < 100; i++) { 26 | Thread.sleep(random.nextInt(20)); 27 | queue.offer("hi date:" + new Date()); 28 | } 29 | } catch (InterruptedException e) { 30 | e.printStackTrace(); 31 | Thread.currentThread().interrupt(); 32 | } 33 | } 34 | 35 | public void stop() { 36 | isRunning = false; 37 | System.out.println(Thread.currentThread().getId() + " thread is stop"); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/queue/BoundedBufferQueue.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.queue; 2 | 3 | import java.util.concurrent.locks.Condition; 4 | import java.util.concurrent.locks.ReentrantLock; 5 | 6 | /** 7 | * 有界阻塞缓冲队列 8 | * User: krisjin 9 | * Date: 2016/2/16 10 | */ 11 | public class BoundedBufferQueue { 12 | 13 | private final ReentrantLock lock; 14 | private final Condition notEmpty; 15 | private final Condition notFull; 16 | private Object[] buffer; 17 | private int count; 18 | private int putIndex; 19 | private int takeIndex; 20 | 21 | /** 22 | * 初始化队列大小 23 | * 24 | * @param size 25 | */ 26 | public BoundedBufferQueue(int size) { 27 | buffer = new Object[size]; 28 | lock = new ReentrantLock(); 29 | notEmpty = lock.newCondition(); 30 | notFull = lock.newCondition(); 31 | } 32 | 33 | public void put(E e) throws InterruptedException { 34 | lock.lock(); 35 | try { 36 | while (count == buffer.length) { 37 | notFull.await(); 38 | } 39 | buffer[putIndex] = e; 40 | 41 | if (++putIndex == buffer.length) { 42 | putIndex = 0; 43 | } 44 | count++; 45 | notEmpty.signal(); 46 | } finally { 47 | lock.unlock(); 48 | } 49 | } 50 | 51 | public E take() throws InterruptedException { 52 | lock.lock(); 53 | 54 | try { 55 | while (count == 0) { 56 | notEmpty.await(); 57 | } 58 | E e = (E) buffer[takeIndex]; 59 | count--; 60 | 61 | if (++takeIndex == buffer.length) { 62 | takeIndex = 0; 63 | } 64 | notFull.signal(); 65 | return e; 66 | } finally { 67 | lock.unlock(); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/queue/BoundedBufferQueueTest.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.queue; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | 6 | /** 7 | * User: krisjin 8 | * Date: 2016/2/16 9 | */ 10 | public class BoundedBufferQueueTest { 11 | 12 | public static void main(String[] args) { 13 | BoundedBufferQueue queue = new BoundedBufferQueue<>(1200); 14 | ExecutorService executorService = Executors.newCachedThreadPool(); 15 | executorService.execute(new Producer(queue)); 16 | executorService.execute(new Consumer(queue)); 17 | } 18 | 19 | // 20 | static class Producer implements Runnable { 21 | private BoundedBufferQueue queue; 22 | 23 | public Producer(BoundedBufferQueue queue) { 24 | this.queue = queue; 25 | } 26 | 27 | @Override 28 | public void run() { 29 | while (true) { 30 | int num = (int) (Math.random() * 100); 31 | try { 32 | queue.put(num); 33 | System.out.println(Thread.currentThread().getName() + " producer " + num); 34 | } catch (InterruptedException e) { 35 | e.printStackTrace(); 36 | } 37 | } 38 | } 39 | } 40 | 41 | static class Consumer implements Runnable { 42 | 43 | private BoundedBufferQueue queue; 44 | 45 | public Consumer(BoundedBufferQueue queue) { 46 | this.queue = queue; 47 | } 48 | 49 | @Override 50 | public void run() { 51 | while (true) { 52 | try { 53 | Integer num = (Integer) queue.take(); 54 | System.out.println(Thread.currentThread().getName() + " consume " + num); 55 | } catch (InterruptedException e) { 56 | e.printStackTrace(); 57 | } 58 | } 59 | } 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/queue/ConsumerProducer.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.queue; 2 | 3 | import java.util.concurrent.BlockingQueue; 4 | import java.util.concurrent.LinkedBlockingDeque; 5 | 6 | /** 7 | * User: krisjin 8 | * Date: 2016/1/19 9 | */ 10 | public class ConsumerProducer { 11 | 12 | public static void main(String[] args) { 13 | BlockingQueue queue = new LinkedBlockingDeque(); 14 | Consumer consumer = new Consumer(queue); 15 | Producer producer = new Producer(queue); 16 | new Thread(producer).start(); 17 | new Thread(consumer).start(); 18 | 19 | } 20 | 21 | //消费者 22 | static class Consumer implements Runnable { 23 | private BlockingQueue blockingQueue; 24 | 25 | public Consumer(BlockingQueue queue) { 26 | this.blockingQueue = queue; 27 | } 28 | 29 | @Override 30 | public void run() { 31 | while (true) { 32 | try { 33 | //阻塞式消费 34 | Object val = blockingQueue.take(); 35 | System.out.println("消费信息:" + val); 36 | } catch (InterruptedException e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | } 41 | } 42 | 43 | //生产者 44 | static class Producer implements Runnable { 45 | private final BlockingQueue blockingQueue; 46 | 47 | public Producer(BlockingQueue queue) { 48 | this.blockingQueue = queue; 49 | } 50 | 51 | @Override 52 | public void run() { 53 | for (int i = 0; i < 100; i++) { 54 | try { 55 | //生产消息(阻塞) 56 | blockingQueue.put(i + ":message"); 57 | System.out.println("生产消息:" + i + ":message"); 58 | } catch (InterruptedException e) { 59 | e.printStackTrace(); 60 | } 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/queue/Java_bloking_queue.md: -------------------------------------------------------------------------------- 1 | 2 | ## 什么是阻塞队列? 3 | 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时, 4 | 存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程, 5 | 消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。 -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/reentrant/ReentrantLockDemo.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.reentrant; 2 | 3 | import java.util.concurrent.locks.ReentrantLock; 4 | 5 | /** 6 | * User : krisjin 7 | * Date: 2015/9/8 8 | */ 9 | public class ReentrantLockDemo implements Runnable { 10 | 11 | private ReentrantLock lock = new ReentrantLock(); 12 | 13 | public static void main(String[] args) { 14 | ReentrantLockDemo reentrantLockDemo = new ReentrantLockDemo(); 15 | new Thread(reentrantLockDemo).start(); 16 | new Thread(reentrantLockDemo).start(); 17 | } 18 | 19 | public void get() { 20 | lock.lock(); 21 | System.out.println(Thread.currentThread().getId()); 22 | set(); 23 | lock.unlock(); 24 | } 25 | 26 | public void set() { 27 | lock.lock(); 28 | System.out.println(Thread.currentThread().getId()); 29 | lock.unlock(); 30 | } 31 | 32 | @Override 33 | public void run() { 34 | get(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/reentrant/ReentrantLockSynchronizedDemo.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.reentrant; 2 | 3 | /** 4 | * synchronized 可重入锁 5 | * User : krisjin 6 | * Date: 2015/9/8 7 | */ 8 | public class ReentrantLockSynchronizedDemo implements Runnable { 9 | 10 | public static void main(String[] args) { 11 | ReentrantLockSynchronizedDemo demo01 = new ReentrantLockSynchronizedDemo(); 12 | new Thread(demo01).start(); 13 | new Thread(demo01).start(); 14 | new Thread(demo01).start(); 15 | } 16 | 17 | public synchronized void get() { 18 | System.out.println(Thread.currentThread().getId()); 19 | set(); 20 | } 21 | 22 | public synchronized void set() { 23 | System.out.println(Thread.currentThread().getId()); 24 | } 25 | 26 | @Override 27 | public void run() { 28 | get(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/reentrant/SpinLock.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.reentrant; 2 | 3 | import java.util.concurrent.atomic.AtomicReference; 4 | 5 | /** 6 | * User : krisjin 7 | * Date: 2015/9/8 8 | */ 9 | public class SpinLock { 10 | 11 | private AtomicReference owner = new AtomicReference(); 12 | 13 | public void lock() { 14 | 15 | Thread thread = Thread.currentThread(); 16 | while (!owner.compareAndSet(null, thread)) { 17 | } 18 | } 19 | 20 | public void unlock() { 21 | Thread thread = Thread.currentThread(); 22 | owner.compareAndSet(thread, null); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/reentrant/SpinLock2.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.reentrant; 2 | 3 | import java.util.concurrent.atomic.AtomicReference; 4 | 5 | /** 6 | * 采用计数次进行统计,解决了自旋锁的死锁问题,该自旋锁即为可重入锁。 7 | * User : krisjin 8 | * Date: 2015/9/8 9 | */ 10 | public class SpinLock2 { 11 | 12 | private AtomicReference owner = new AtomicReference(); 13 | private int count = 0; 14 | 15 | public void lock() { 16 | Thread currentThread = Thread.currentThread(); 17 | if (currentThread == owner.get()) { 18 | count++; 19 | return; 20 | } 21 | 22 | while (!owner.compareAndSet(null, currentThread)) { 23 | } 24 | } 25 | 26 | public void unlock() { 27 | Thread currentThread = Thread.currentThread(); 28 | if (owner.get() == currentThread) { 29 | if (count != 0) { 30 | count--; 31 | } else { 32 | owner.compareAndSet(currentThread, null); 33 | } 34 | 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/reentrant/SpinLockTest.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.reentrant; 2 | 3 | /** 4 | * 若有同一线程两调用lock() ,会导致第二次调用lock位置进行自旋,产生了死锁 5 | * 说明这个锁并不是可重入的。(在lock函数内,应验证线程是否为已经获得锁的线程) 6 | *

7 | * User : krisjin 8 | * Date: 2015/9/8 9 | * Time: 16:16 10 | */ 11 | public class SpinLockTest implements Runnable { 12 | 13 | // private SpinLock lock = new SpinLock(); 14 | private SpinLock2 lock = new SpinLock2(); 15 | 16 | public static void main(String[] args) { 17 | SpinLockTest spinLockTest = new SpinLockTest(); 18 | new Thread(spinLockTest).start(); 19 | new Thread(spinLockTest).start(); 20 | } 21 | 22 | public void get() { 23 | lock.lock(); 24 | System.out.println(Thread.currentThread().getId()); 25 | register(); 26 | lock.unlock(); 27 | } 28 | 29 | public void register() { 30 | lock.lock(); 31 | System.out.println(Thread.currentThread().getId()); 32 | lock.unlock(); 33 | } 34 | 35 | @Override 36 | public void run() { 37 | get(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/reference/WeakReferenceExam.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.reference; 2 | 3 | import java.lang.ref.WeakReference; 4 | 5 | /** 6 | * 7 | * 弱引用对象的存在不会阻止它所指向的对象被垃圾回收器回收。弱引用最常见的用途是实现规范映射(canonicalizing mappings,比如哈希表)。 8 | * 假设垃圾收集器在某个时间点决定一个对象是弱可达的(weakly reachable)(也就是说当前指向它的全都是弱引用),这时垃圾收集器会清除所有指向该对象的弱引用, 9 | * 然后垃圾收集器会把这个弱可达对象标记为可终结(finalizable)的,这样它们随后就会被回收。与此同时或稍后, 10 | * 垃圾收集器会把那些刚清除的弱引用放入创建弱引用对象时所登记到的引用队列(Reference Queue)中。 11 | * @author krisjin 12 | * @date 2020/11/2 13 | */ 14 | public class WeakReferenceExam { 15 | //execute gc , weak reference is collection 16 | static WeakReference name = new WeakReference(new String("kris")); 17 | 18 | public static void main(String[] args) { 19 | System.gc(); 20 | if (name.get() != null) { 21 | System.err.println("没回收"); 22 | } else { 23 | System.out.println("已回收"); 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/resourcepool/ResourcePool.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.resourcepool; 2 | 3 | import java.util.List; 4 | import java.util.concurrent.BlockingQueue; 5 | import java.util.concurrent.LinkedBlockingQueue; 6 | import java.util.concurrent.Semaphore; 7 | import java.util.concurrent.TimeUnit; 8 | 9 | /** 10 | * 一些资源可能是有限的,并且确保并发编程中的限制是重要的。 11 | * 建立限制资源使用的机制。 它会阻止 用户没有可用的时候。 它使用Semaphores实现并发线程安全池。 12 | */ 13 | public class ResourcePool { 14 | private final static TimeUnit TIME_UNIT = TimeUnit.SECONDS; 15 | private Semaphore semaphore; 16 | private BlockingQueue resources; 17 | 18 | public ResourcePool(int poolSize, List initializedResources) { 19 | this.semaphore = new Semaphore(poolSize, true); 20 | this.resources = new LinkedBlockingQueue<>(poolSize); 21 | this.resources.addAll(initializedResources); 22 | } 23 | 24 | public T get() throws InterruptedException { 25 | return get(Integer.MAX_VALUE); 26 | } 27 | 28 | public T get(long secondsToTimeout) throws InterruptedException { 29 | semaphore.acquire(); 30 | try { 31 | T resource = resources.poll(secondsToTimeout, TIME_UNIT); 32 | return resource; 33 | } finally { 34 | semaphore.release(); 35 | } 36 | } 37 | 38 | public void release(T resource) throws InterruptedException { 39 | if (resource != null) { 40 | resources.put(resource); 41 | semaphore.release(); 42 | } 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/resourcepool/ResourcePoolUsage.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.resourcepool; 2 | 3 | import java.util.Arrays; 4 | import java.util.Random; 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.Executors; 7 | 8 | public class ResourcePoolUsage { 9 | 10 | public static void main(String[] args) { 11 | ExecutorService executor = Executors.newCachedThreadPool(); 12 | ResourcePool pool = new ResourcePool(15, 13 | Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12, 13, 14)); 14 | Random random = new Random(); 15 | for (int i = 0; i < 30; i++) { 16 | executor.execute(() -> { 17 | try { 18 | Object value = pool.get(60); 19 | System.out.println("Value taken: " + value); 20 | Thread.sleep(random.nextInt(5000)); 21 | pool.release(value); 22 | System.out.println("Value released " + value); 23 | } catch (InterruptedException e) { 24 | e.printStackTrace(); 25 | } 26 | }); 27 | } 28 | executor.shutdown(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/sort/SortTask.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.sort; 2 | 3 | import java.util.List; 4 | import java.util.concurrent.BrokenBarrierException; 5 | import java.util.concurrent.CyclicBarrier; 6 | 7 | /** 8 | * User:krisjin 9 | * Date:2019/2/24 10 | */ 11 | public class SortTask implements Runnable { 12 | 13 | private final int[] numArr; 14 | private List resultData; 15 | private CyclicBarrier cyclicBarrier; 16 | 17 | public SortTask(CyclicBarrier cyclicBarrier, final int[] numArr, List resultData) { 18 | this.numArr = numArr; 19 | this.resultData = resultData; 20 | this.cyclicBarrier = cyclicBarrier; 21 | } 22 | 23 | @Override 24 | public void run() { 25 | 26 | sort(numArr, 0, numArr.length - 1); 27 | synchronized (resultData) { 28 | resultData.add(numArr); 29 | } 30 | try { 31 | cyclicBarrier.await(); 32 | } catch (InterruptedException e) { 33 | e.printStackTrace(); 34 | } catch (BrokenBarrierException e) { 35 | e.printStackTrace(); 36 | } 37 | } 38 | 39 | 40 | public static void sort(int numArr[], int low, int high) { 41 | int i, j, index; 42 | if (low > high) { 43 | return; 44 | } 45 | i = low; 46 | j = high; 47 | index = numArr[i]; // 用子表的第一个记录做基准 48 | while (i < j) { // 从表的两端交替向中间扫描 49 | while (i < j && numArr[j] >= index) 50 | j--; 51 | if (i < j) 52 | numArr[i++] = numArr[j];// 用比基准小的记录替换低位记录 53 | while (i < j && numArr[i] < index) 54 | i++; 55 | if (i < j) // 用比基准大的记录替换高位记录 56 | numArr[j--] = numArr[i]; 57 | } 58 | numArr[i] = index;// 将基准数值替换回 a[i] 59 | sort(numArr, low, i - 1); // 对低子表进行递归排序 60 | sort(numArr, i + 1, high); // 对高子表进行递归排序 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/sync/SynIntrinsic.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.sync; 2 | 3 | import org.banyan.concurrent.util.SleepUtil; 4 | 5 | /** 6 | * synchronized使用 7 | * 同步一个方法或一个代码快,同步锁作用对象,没有加同步的方法不会影响 8 | */ 9 | public class SynIntrinsic { 10 | 11 | private Object lock = new Object(); 12 | 13 | /** 14 | * synchronized实例方法使用 15 | */ 16 | public synchronized void synMethod() { 17 | for (int i = 0; i < 10; i++) { 18 | System.out.println(Thread.currentThread().getName() + ":syn method:" + i); 19 | } 20 | } 21 | 22 | /** 23 | * synchronized静态方法使用 24 | */ 25 | public static synchronized void synStatic() { 26 | System.out.println(Thread.currentThread().getName() + ":syn static"); 27 | SleepUtil.second(3); 28 | } 29 | 30 | /** 31 | * synchronized代码块使用 32 | * 使用代码块加锁有哪几种方式,1.对变量加锁,2.this实例对象加锁,3.对象class对象加锁 33 | */ 34 | public void synBlockInVar() { 35 | synchronized (lock) { 36 | for (int i = 0; i < 10; i++) { 37 | System.out.println(Thread.currentThread().getName() + ":syn block:" + i); 38 | } 39 | } 40 | } 41 | 42 | public void synBlockInThis() { 43 | synchronized (this) { 44 | for (int i = 0; i < 10; i++) { 45 | System.out.println(Thread.currentThread().getName() + ":syn block this:" + i); 46 | } 47 | } 48 | } 49 | 50 | public void synBlockInClass() { 51 | synchronized (this) { 52 | for (int i = 0; i < 10; i++) { 53 | System.out.println(Thread.currentThread().getName() + ":syn block this:" + i); 54 | } 55 | } 56 | } 57 | 58 | 59 | /** 60 | * 未使用synchronized 61 | */ 62 | public void normal() { 63 | for (int i = 0; i < 10; i++) { 64 | System.out.println(Thread.currentThread().getName() + ":syn not :" + i); 65 | } 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/sync/SynObjectMain.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.sync; 2 | 3 | /** 4 | * User:krisjin 5 | * Date:2019/3/12 6 | */ 7 | public class SynObjectMain { 8 | 9 | public static void main(String[] args) { 10 | SynIntrinsic synIntrinsic = new SynIntrinsic(); 11 | 12 | Thread t1 = new Thread(new Runnable() { 13 | public void run() { 14 | synIntrinsic.synBlockInVar(); 15 | } 16 | }); 17 | 18 | Thread t2 = new Thread(new Runnable() { 19 | public void run() { 20 | synIntrinsic.synMethod(); 21 | } 22 | }); 23 | 24 | Thread t3 = new Thread(new Runnable() { 25 | public void run() { 26 | synIntrinsic.normal(); 27 | } 28 | }); 29 | 30 | t1.start(); 31 | t2.start(); 32 | t3.start(); 33 | } 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/sync/UsingBarriers.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.sync; 2 | 3 | import java.util.Random; 4 | import java.util.concurrent.BrokenBarrierException; 5 | import java.util.concurrent.CyclicBarrier; 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | 9 | /** 10 | * 基础的同步器,JUC提供了很多的具体的同步实现类,这些不同的同步类对应了搁置的应用场景,在并发编程中,特别是大数据开源框架中 11 | * Barriers are used for blocking a group of threads until they come together at 12 | * a single point in order to proceed. Basically, convergence of threads. 13 | *

14 | * Accepts a runnable in it's constructor to be called when the threads reach the 15 | * barrier, but before its unblocked 16 | *

17 | * Most common implementation is cyclic barrier. 18 | */ 19 | public class UsingBarriers { 20 | 21 | public static void main(String[] args) { 22 | ExecutorService executor = Executors.newCachedThreadPool(); 23 | Runnable barrierAction = () -> System.out.println("Well done, guys!"); 24 | CyclicBarrier barrier = new CyclicBarrier(11, barrierAction); 25 | System.out.println(System.getProperty("java.home")); 26 | Runnable task = () -> { 27 | try { 28 | // simulating a task that can take at most 1sec to run 29 | System.out.println("Doing task for " + Thread.currentThread().getName()); 30 | Thread.sleep(10); 31 | System.out.println("Done for " + Thread.currentThread().getName()); 32 | barrier.await(); 33 | } catch (InterruptedException | BrokenBarrierException e) { 34 | e.printStackTrace(); 35 | } 36 | }; 37 | 38 | for (int i = 0; i < 10; i++) { 39 | executor.execute(task); 40 | } 41 | executor.shutdown(); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/sync/UsingLatches.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.sync; 2 | 3 | import java.util.concurrent.CountDownLatch; 4 | import java.util.concurrent.ExecutorService; 5 | import java.util.concurrent.Executors; 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Latches are used to delay the progress of threads until it reach a terminal 10 | * state 11 | * 12 | * Most common implementation is CountDownLatch. 13 | * 14 | * In CountDownLatch, each event adds 1. When ready, countDown() is called, 15 | * decrementing by counter by 1. await() method releases when counter is 0. 16 | * 17 | * LazyInitSingleton use synchronizer. 18 | */ 19 | public class UsingLatches { 20 | 21 | public static void main(String[] args) { 22 | ExecutorService executor = Executors.newCachedThreadPool(); 23 | CountDownLatch latch = new CountDownLatch(3); 24 | Runnable r = () -> { 25 | try { 26 | Thread.sleep(1000); 27 | System.out.println("TaskService in " + Thread.currentThread().getName() + " initialized."); 28 | latch.countDown(); 29 | } catch (InterruptedException e) { 30 | e.printStackTrace(); 31 | } 32 | }; 33 | executor.execute(r); 34 | executor.execute(r); 35 | executor.execute(r); 36 | try { 37 | latch.await(2, TimeUnit.SECONDS); 38 | System.out.println("All services up and running!"); 39 | } catch (InterruptedException e) { 40 | e.printStackTrace(); 41 | } 42 | executor.shutdown(); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/task/CallableFuture.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.task; 2 | 3 | import java.util.concurrent.*; 4 | import java.util.concurrent.atomic.AtomicLong; 5 | 6 | /** 7 | * 使用Callable 和 Future 返回线程执行结果 8 | */ 9 | public class CallableFuture { 10 | static ExecutorService executorService = Executors.newFixedThreadPool(20); 11 | static AtomicLong num = new AtomicLong(1); 12 | 13 | public static void main() throws InterruptedException { 14 | for (int i = 0; i < 100; i++) { 15 | Task task = new Task("序表达式(Ranking Formula)允许用户为应用自定义搜索结果排序方式,通过在查询请求中指定表达式来对结果排序。排序表达式支持基本运算(算术运算、关系运算、逻辑运算、位运算、条件运算)、数学函数和排序特征(feature)等。Open Search对于几种经典的应用(如论坛、资讯等)提供了表达式模板,用户可根据自己数据的特点,选择合适的表达式模板,并以此为基础进行修改,生成自己的表达式。", num); 16 | 17 | Future future = executorService.submit(task); 18 | } 19 | 20 | System.out.println("####################################"); 21 | // executorService.shutdown(); 22 | // TimeUnit.MILLISECONDS.sleep(100); 23 | 24 | // try { 25 | // Integer result = future.get(); 26 | System.out.println("task execute result is : "); 27 | // } catch (InterruptedException e) { 28 | // e.printStackTrace(); 29 | // } catch (ExecutionException e) { 30 | // e.printStackTrace(); 31 | // } 32 | } 33 | 34 | static class Task implements Callable { 35 | String msg; 36 | AtomicLong num; 37 | 38 | public Task(String msg, AtomicLong num) { 39 | this.msg = msg; 40 | this.num = num; 41 | } 42 | 43 | @Override 44 | public Long call() { 45 | System.out.println("任务线程在进行计算" + num.incrementAndGet()); 46 | 47 | return num.get(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/task/CallableFutureTask.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.task; 2 | 3 | import java.util.concurrent.*; 4 | 5 | /** 6 | * Date: 2015/9/22 7 | * Time: 11:03 8 | */ 9 | public class CallableFutureTask { 10 | 11 | public static void main(String[] args) throws InterruptedException { 12 | 13 | Task task = new Task(); 14 | 15 | FutureTask futureTask = new FutureTask(task); 16 | 17 | //第一种执行方式 18 | // ExecutorService executor = Executors.newFixedThreadPool(2); 19 | // executor.submit(futureTask); 20 | // executor.shutdown(); 21 | 22 | //第二种执行方式 23 | Thread thread = new Thread(futureTask); 24 | thread.start(); 25 | 26 | //主线程休眠1秒钟,CPU执行让给其它线程. 27 | TimeUnit.MILLISECONDS.sleep(1000); 28 | System.out.println("主线程在执行任务"); 29 | try { 30 | futureTask.cancel(true); 31 | System.out.println(futureTask.isCancelled()); 32 | 33 | Integer result = futureTask.get(); 34 | System.out.println("task execute result is : " + result); 35 | } catch (InterruptedException e) { 36 | e.printStackTrace(); 37 | } catch (ExecutionException e) { 38 | e.printStackTrace(); 39 | } catch (CancellationException cancellationException) { 40 | cancellationException.printStackTrace(); 41 | } 42 | } 43 | 44 | static class Task implements Callable { 45 | @Override 46 | public Integer call() throws Exception { 47 | //让任务线程睡眠,以便取消当前线程,如果线程已执行完成,取消线程的工作将没有效果。 48 | TimeUnit.MILLISECONDS.sleep(1000); 49 | System.out.println("任务线程在进行计算"); 50 | int sum = 0; 51 | for (int i = 0; i < 100; i++) { 52 | sum += i; 53 | } 54 | return sum; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/task/README.md: -------------------------------------------------------------------------------- 1 | ### 介绍 2 | 大多数并发应用程序都是围绕"任务执行"来构造的:任务通常是一些抽象的 3 | 且离散的工作单元。通过把应用程序的工作分解到多个任务中,可以简化程序的 4 | 组织结构,提供一种自然的事务边界来优化错误恢复过程,以及提供一种自然的 5 | 并行工作结构来提升并发性。 6 | 7 | 在线程中执行任务 -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/task/async/TaskCallback.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.task.async; 2 | 3 | 4 | public abstract class TaskCallback { 5 | 6 | /** 7 | * 执行动作 8 | */ 9 | public abstract TaskFuture apply(TaskFuture f); 10 | 11 | public TaskCallback compose(final TaskCallback before) { 12 | return new TaskCallback() { 13 | @Override 14 | public TaskFuture apply(TaskFuture f) { 15 | return TaskCallback.this.apply(before.apply(f)); 16 | } 17 | }; 18 | } 19 | 20 | public TaskCallback andThen(final TaskCallback after) { 21 | return new TaskCallback() { 22 | @Override 23 | public TaskFuture apply(TaskFuture f) { 24 | return after.apply(TaskCallback.this.apply(f)); 25 | } 26 | }; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/task/async/TaskFuture.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.task.async; 2 | 3 | import java.util.concurrent.Future; 4 | import java.util.concurrent.TimeUnit; 5 | 6 | 7 | public interface TaskFuture extends Future { 8 | 9 | /** 10 | * 检查任务是否成功完成 11 | * 12 | * @return 13 | */ 14 | boolean isSuccess(); 15 | 16 | /** 17 | * 获取任务失败原因 18 | * 19 | * @return 20 | */ 21 | Throwable cause(); 22 | 23 | /** 24 | * 如果任务完成,则返回任务结果,如果任务失败或者未完成则直接返回 null 25 | * 26 | * @return 27 | */ 28 | Object getNow(); 29 | 30 | /** 31 | * 等待直到任务完成 32 | * 33 | * @return 34 | * @throws InterruptedException 35 | */ 36 | TaskFuture await() throws InterruptedException; 37 | 38 | /** 39 | * 最大等待超时时间,如果任务没完成返回 false, 如果完成则返回 true 40 | * 41 | * @param timeout 最大等待超时时间 42 | * @param unit 超时时间单位 43 | * @return 44 | * @throws InterruptedException 45 | */ 46 | boolean await(long timeout, TimeUnit unit) throws InterruptedException; 47 | 48 | /** 49 | * 任务完成时回调动作 50 | * 51 | * @param callback 回调动作 52 | * @return 53 | */ 54 | TaskFuture onComplete(TaskCallback callback); 55 | 56 | /** 57 | * 任务成功时回调动作 58 | * 59 | * @param callback 回调动作 60 | * @return 61 | */ 62 | TaskFuture onSuccess(TaskCallback callback); 63 | 64 | /** 65 | * 任务失败时回调动作 66 | * 67 | * @param callback 回调动作 68 | * @return 69 | */ 70 | TaskFuture onFailure(TaskCallback callback); 71 | 72 | boolean hasAttr(String key); 73 | 74 | Object getAttr(String key); 75 | 76 | TaskFuture addAttr(String key, Object value); 77 | 78 | Object removeAttr(String key); 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/task/async/TaskPromise.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.task.async; 2 | 3 | 4 | public interface TaskPromise extends TaskFuture { 5 | 6 | /** 7 | * 获取和 Promise 关联的 Future 8 | * 9 | * @return 10 | */ 11 | TaskFuture getFuture(); 12 | 13 | /** 14 | * 标记任务成功完成, 如果任务已经完成,则可能抛出 {@code IllegalStateException} 15 | * 16 | * @param result 任务结果 17 | * @return 18 | */ 19 | TaskPromise setSuccess(Object result); 20 | 21 | /** 22 | * 尝试标记任务成功完成 23 | * 24 | * @param result 任务结果 25 | * @return 26 | */ 27 | boolean trySuccess(Object result); 28 | 29 | /** 30 | * 标记任务完成失败, 如果任务已经完成,则可能抛出 {@link IllegalStateException} 31 | * 32 | * @param cause 失败原因 33 | * @return 34 | */ 35 | TaskPromise setFailure(Throwable cause); 36 | 37 | /** 38 | * 尝试标记任务完成失败, 如果任务已经完成,则可能抛出 {@link IllegalStateException} 39 | * 40 | * @param cause 失败原因 41 | * @return 42 | */ 43 | boolean tryFailure(Throwable cause); 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/task/async/Test.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.task.async; 2 | 3 | import java.util.concurrent.CountDownLatch; 4 | import java.util.concurrent.ExecutionException; 5 | 6 | /** 7 | * User: krisjin 8 | * Date: 2016/2/16 9 | */ 10 | public class Test { 11 | public static void main(String[] args) throws InterruptedException, ExecutionException { 12 | test1(); 13 | } 14 | 15 | /** 16 | * 异步执行任务,获得 Future 后添加 Callback 17 | * 18 | * @throws InterruptedException 19 | */ 20 | private static void test1() throws InterruptedException, ExecutionException { 21 | 22 | final TaskPromise promise = new DefaultTaskPromise(); 23 | final TaskFuture future = promise.getFuture(); 24 | final CountDownLatch latch = new CountDownLatch(1); 25 | 26 | // TaskFuture taskFuture = future.onComplete(new TaskCallback() { // 添加结束 Callback 27 | // @Override 28 | // public TaskFuture apply(TaskFuture f) { 29 | // latch.countDown(); 30 | // return f; 31 | // } 32 | // }); 33 | // future.onSuccess(new TaskCallback() { 34 | // @Override 35 | // public TaskFuture apply(TaskFuture f) { 36 | // System.out.println("success process....."); 37 | // return f; 38 | // } 39 | // }); 40 | new Thread(new Runnable() { 41 | @Override 42 | public void run() { 43 | promise.setSuccess("done"); 44 | 45 | } 46 | }).start(); 47 | System.out.println(future.get()); 48 | latch.await(); 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/PipedStream.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread; 2 | 3 | import java.io.IOException; 4 | import java.io.PipedInputStream; 5 | import java.io.PipedOutputStream; 6 | 7 | /** 8 | * User: krisjin 9 | * Date: 2016/2/14 10 | */ 11 | public class PipedStream { 12 | 13 | public static void main(String... args) throws IOException { 14 | PipedOutputStream out = new PipedOutputStream(); 15 | PipedInputStream in = new PipedInputStream(); 16 | 17 | out.connect(in); 18 | Thread thread = new Thread(new Print(in), "PrintThread"); 19 | thread.start(); 20 | 21 | int receive = 0; 22 | while ((receive = System.in.read()) != -1) { 23 | out.write(receive); 24 | } 25 | } 26 | 27 | static class Print implements Runnable { 28 | 29 | private PipedInputStream in; 30 | 31 | public Print(PipedInputStream in) { 32 | this.in = in; 33 | } 34 | 35 | @Override 36 | public void run() { 37 | int receive = 0; 38 | try { 39 | while ((receive = in.read()) != -1) { 40 | System.out.println(receive); 41 | } 42 | } catch (IOException e) { 43 | e.printStackTrace(); 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/ThreadDaemon.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread; 2 | 3 | import org.banyan.concurrent.util.SleepUtil; 4 | 5 | /** 6 | * 守护线程 7 | * Daemon线程是一种守护型线程,因为它主要用作程序中后台调度与支持性工作。 8 | * 这意味着当一个Java虚拟机中没有一个非守护线程时,Java虚拟机将退出。 9 | * 在构建守护线程时不能依赖finally块中的操作来确保执行关闭和清理资源的逻辑。 10 | * User: krisjin 11 | * Date: 2016/2/5 12 | */ 13 | public class ThreadDaemon { 14 | 15 | public static void main(String... args) { 16 | Thread thread = new Thread(new DaemonRunner(), "DaemonRunner"); 17 | //在线程启动之前设置 18 | thread.setDaemon(true); 19 | thread.start(); 20 | } 21 | 22 | static class DaemonRunner implements Runnable { 23 | @Override 24 | public void run() { 25 | try { 26 | SleepUtil.second(10); 27 | } finally { 28 | System.out.println("DaemonThread finally run."); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/ThreadDeprecated.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread; 2 | 3 | import org.banyan.concurrent.util.SleepUtil; 4 | 5 | import java.text.DateFormat; 6 | import java.text.SimpleDateFormat; 7 | import java.util.Date; 8 | 9 | /** 10 | * 线程过时的方法 11 | * User: krisjin 12 | * Date: 2016/2/5 13 | */ 14 | public class ThreadDeprecated { 15 | 16 | public static void main(String[] args) { 17 | DateFormat format = new SimpleDateFormat("HH:mm:ss"); 18 | Thread printThread = new Thread(new Runner(), "PrintThread"); 19 | printThread.setDaemon(true); 20 | 21 | printThread.start(); 22 | SleepUtil.second(3); 23 | 24 | printThread.suspend(); 25 | System.out.println("main suspend PrintThread at " + format.format(new Date())); 26 | SleepUtil.second(3); 27 | 28 | printThread.resume(); 29 | System.out.println("main resume PrintThread at " + format.format(new Date())); 30 | SleepUtil.second(3); 31 | 32 | printThread.stop(); 33 | System.out.println("main stop PrintThread at " + format.format(new Date())); 34 | SleepUtil.second(3); 35 | } 36 | 37 | static class Runner implements Runnable { 38 | DateFormat format = new SimpleDateFormat("HH:mm:ss"); 39 | 40 | @Override 41 | public void run() { 42 | while (true) { 43 | System.out.println(Thread.currentThread().getName() + " Run at " + format.format(new Date())); 44 | SleepUtil.second(1); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/ThreadInterrupted.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread; 2 | 3 | import org.banyan.concurrent.util.SleepUtil; 4 | 5 | /** 6 | * 中断可以理解为线程的一个表示位属性 7 | * User: krisjin 8 | * Date: 2016/2/5 9 | */ 10 | public class ThreadInterrupted { 11 | 12 | public static void main(String... args) throws Exception { 13 | Thread sleepRunner = new Thread(new SleepRunner(), "SleepThread"); 14 | sleepRunner.setDaemon(true); 15 | Thread busyRunner = new Thread(new BusyRunner(), "BusyThread"); 16 | busyRunner.setDaemon(true); 17 | sleepRunner.start(); 18 | busyRunner.start(); 19 | //休眠5秒,让sleepRunner和busyRunner充分运行 20 | SleepUtil.second(5); 21 | 22 | sleepRunner.interrupt(); 23 | busyRunner.interrupt(); 24 | System.out.println("SleepThread interrupt is:" + sleepRunner.isInterrupted()); 25 | System.out.println("BusyThread interrupt is:" + busyRunner.isInterrupted()); 26 | SleepUtil.second(2); 27 | } 28 | 29 | static class SleepRunner implements Runnable { 30 | @Override 31 | public void run() { 32 | while (true) 33 | SleepUtil.second(10); 34 | } 35 | } 36 | 37 | static class BusyRunner implements Runnable { 38 | @Override 39 | public void run() { 40 | while (true) ; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/ThreadJoin.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread; 2 | 3 | /** 4 | * join线程间写作 5 | * 6 | * @author krisjin 7 | * @date 2020/11/19 8 | */ 9 | public class ThreadJoin { 10 | public static void main(String[] args) throws InterruptedException { 11 | // Thread t1 = new Thread(() -> { 12 | // System.err.println(Thread.currentThread().getName() + " thread execute end..."); 13 | // }); 14 | // 15 | // Thread t2 = new Thread(() -> { 16 | // System.err.println(Thread.currentThread().getName() + " thread execute end..."); 17 | // }); 18 | // 19 | // t1.setName("t1"); 20 | // t1.start(); 21 | // 22 | // t2.setName("t2"); 23 | // t2.start(); 24 | // 25 | // t1.join(); 26 | // t2.join(); 27 | // 28 | // System.err.println("main thread execute end..."); 29 | 30 | test2(); 31 | 32 | } 33 | 34 | 35 | public static void test2() { 36 | Thread t2 = new Thread(() -> { 37 | System.err.println("t2..."); 38 | }); 39 | Thread t1 = new Thread(() -> { 40 | try { 41 | t2.join(); 42 | } catch (InterruptedException e) { 43 | throw new RuntimeException(e); 44 | } 45 | System.err.println("t1..."); 46 | 47 | }); 48 | 49 | 50 | t1.start(); 51 | t2.start(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/ThreadMXBeanExample.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread; 2 | 3 | import java.lang.management.ManagementFactory; 4 | import java.lang.management.ThreadInfo; 5 | import java.lang.management.ThreadMXBean; 6 | 7 | /** 8 | * User: krisjin 9 | * Date: 2016/2/3 10 | */ 11 | public class ThreadMXBeanExample { 12 | 13 | public static void main(String... args) { 14 | ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); 15 | ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(true, true); 16 | for (ThreadInfo threadInfo : threadInfos) { 17 | long threadId = threadInfo.getThreadId(); 18 | String threadName = threadInfo.getThreadName(); 19 | Thread.State state = threadInfo.getThreadState(); 20 | System.out.println(threadInfo.toString()); 21 | // System.out.println("Thread id:" + threadId + " ;Thread name:" + threadName + "; Thread state:" + state.name()); 22 | } 23 | 24 | threads(); 25 | } 26 | 27 | 28 | private static void threads(){ 29 | 30 | Thread[] t = new Thread[Thread.activeCount()]; 31 | 32 | 33 | int threadCount = Thread.enumerate(t); 34 | 35 | for (int i=0;i jobList = new ArrayList(); 23 | for (int i = 0; i < 10; i++) { 24 | int priority = i < 5 ? Thread.MIN_PRIORITY : Thread.MAX_PRIORITY; 25 | Job job = new Job(priority); 26 | jobList.add(job); 27 | Thread thread = new Thread(job, "Thread:" + i); 28 | thread.setPriority(priority); 29 | thread.start(); 30 | } 31 | notStart = false; 32 | TimeUnit.MILLISECONDS.sleep(10); 33 | notEnd = false; 34 | 35 | for (Job job : jobList) { 36 | System.out.println("Job priority:" + job.priority + ", count:" + job.jobCount); 37 | } 38 | } 39 | 40 | static class Job implements Runnable { 41 | private int priority; 42 | private long jobCount; 43 | 44 | public Job(int priority) { 45 | this.priority = priority; 46 | } 47 | 48 | @Override 49 | public void run() { 50 | while (notStart) Thread.yield(); 51 | 52 | while (notEnd) { 53 | Thread.yield(); 54 | jobCount++; 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/ThreadShutdown.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread; 2 | 3 | import org.banyan.concurrent.util.SleepUtil; 4 | 5 | /** 6 | * 安全的终结线程 7 | * User: krisjin 8 | * Date: 2016/2/5 9 | */ 10 | public class ThreadShutdown { 11 | 12 | public static void main(String... args) { 13 | Thread countThread = new Thread(new Runner(), "CountThread"); 14 | countThread.start(); 15 | //休眠1秒,main线程对CountThread进行中断,使CountThread能够感知中断而结束 16 | SleepUtil.second(1); 17 | countThread.interrupt(); 18 | Runner runner = new Runner(); 19 | 20 | countThread = new Thread(runner, "CountThread"); 21 | countThread.start(); 22 | //休眠1秒 23 | SleepUtil.second(1); 24 | runner.cancel(); 25 | } 26 | 27 | static class Runner implements Runnable { 28 | private long i; 29 | private volatile boolean on = true; 30 | 31 | @Override 32 | public void run() { 33 | while (on && !Thread.currentThread().isInterrupted()) { 34 | i++; 35 | } 36 | System.out.println(i); 37 | } 38 | 39 | public void cancel() { 40 | on = false; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/ThreadState.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread; 2 | 3 | import org.banyan.concurrent.util.SleepUtil; 4 | 5 | /** 6 | * 线程状态,使用jstack命令打印堆栈信息查看 7 | * User: krisjin 8 | * Date: 2016/2/4 9 | */ 10 | public class ThreadState { 11 | 12 | public static void main(String... args) { 13 | new Thread(new TimeWaiting(), "TimeWaitingThread").start(); 14 | new Thread(new Waiting(), "WaitingThread").start(); 15 | 16 | //使用两个Blocked线程,一个获取锁成功,另一个被阻塞 17 | new Thread(new Blocked(), "BlockedThread-1").start(); 18 | new Thread(new Blocked(), "BlockedThread-2").start(); 19 | } 20 | 21 | //线程不断地进行睡眠 22 | static class TimeWaiting implements Runnable { 23 | @Override 24 | public void run() { 25 | while (true) { 26 | SleepUtil.second(100); 27 | } 28 | } 29 | } 30 | 31 | //线程在Waiting class实例上等待 32 | static class Waiting implements Runnable { 33 | @Override 34 | public void run() { 35 | while (true) { 36 | synchronized (Waiting.class) { 37 | try { 38 | Waiting.class.wait(); 39 | } catch (InterruptedException e) { 40 | e.printStackTrace(); 41 | } 42 | } 43 | } 44 | } 45 | } 46 | 47 | //线程在Blocked.class实例上加锁后,不会释放该锁 48 | static class Blocked implements Runnable { 49 | @Override 50 | public void run() { 51 | synchronized (Blocked.class) { 52 | while (true) { 53 | SleepUtil.second(100); 54 | } 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/ThreadYield.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread; 2 | 3 | /** 4 | * User: krisjin 5 | * Date: 2016/8/25 6 | */ 7 | public class ThreadYield { 8 | public static void main(String[] args) { 9 | Thread producer = new Producer(); 10 | Thread consumer = new Consumer(); 11 | producer.start(); 12 | consumer.start(); 13 | } 14 | 15 | static class Producer extends Thread { 16 | @Override 17 | public void run() { 18 | for (int i = 1; i <= 5; i++) { 19 | System.out.println("Producer : Produced Item " + i); 20 | Thread.yield(); 21 | } 22 | } 23 | } 24 | 25 | static class Consumer extends Thread { 26 | public void run() { 27 | for (int i = 1; i <= 5; i++) { 28 | System.out.println("Consumer : Consumed Item " + i); 29 | Thread.yield(); 30 | } 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/interrupt/Buffer.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread.interrupt; 2 | 3 | public class Buffer { 4 | private Object lock; 5 | 6 | public Buffer() { 7 | lock = this; 8 | } 9 | 10 | public void write() { 11 | 12 | synchronized (lock) { 13 | long startDate = System.currentTimeMillis(); 14 | for (; ; ) { 15 | if (System.currentTimeMillis() - startDate > Integer.MAX_VALUE) { 16 | break; 17 | } 18 | } 19 | System.out.println("往缓冲区写入数据结束"); 20 | } 21 | } 22 | 23 | public void read() { 24 | 25 | synchronized (lock) { 26 | System.out.println("开始从缓冲区读取数据"); 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/interrupt/BufferInterruptibly.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread.interrupt; 2 | 3 | import java.util.concurrent.locks.ReentrantLock; 4 | 5 | public class BufferInterruptibly { 6 | 7 | private ReentrantLock lock = new ReentrantLock(); 8 | 9 | public void write() { 10 | lock.lock(); 11 | try { 12 | long startTime = System.currentTimeMillis(); 13 | System.out.println("开始往缓冲区写入数据..."); 14 | for (; ; ) { 15 | if (System.currentTimeMillis() - startTime > Integer.MAX_VALUE) { 16 | 17 | break; 18 | } 19 | } 20 | System.out.println("缓冲区写数据结束..."); 21 | } finally { 22 | lock.unlock(); 23 | 24 | } 25 | } 26 | 27 | public void read() throws InterruptedException { 28 | try { 29 | lock.lockInterruptibly(); 30 | 31 | System.out.println("从缓冲区读数据..."); 32 | 33 | } finally { 34 | lock.unlock(); 35 | } 36 | 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/interrupt/Read.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread.interrupt; 2 | 3 | public class Read implements Runnable { 4 | private BufferInterruptibly buffer; 5 | 6 | public Read(BufferInterruptibly buffer) { 7 | this.buffer = buffer; 8 | } 9 | 10 | @Override 11 | public void run() { 12 | try { 13 | buffer.read(); 14 | } catch (InterruptedException e) { 15 | System.out.println("太慢了,不想读了,我去干别的事."); 16 | } 17 | System.out.println("读结束"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/interrupt/Test.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread.interrupt; 2 | 3 | public class Test { 4 | 5 | public static void main(String[] args) { 6 | BufferInterruptibly buffer = new BufferInterruptibly(); 7 | 8 | final Write write = new Write(buffer); 9 | final Read read = new Read(buffer); 10 | 11 | final Thread wThread = new Thread(write); 12 | final Thread rThread = new Thread(read); 13 | wThread.start(); 14 | rThread.start(); 15 | 16 | new Thread(new Runnable() { 17 | 18 | @Override 19 | public void run() { 20 | 21 | long startDate = System.currentTimeMillis(); 22 | 23 | for (; ; ) { 24 | if (System.currentTimeMillis() - startDate > 5000) { 25 | System.out.println("不等了,尝试中断!"); 26 | rThread.interrupt(); 27 | break; 28 | } 29 | } 30 | 31 | } 32 | }).start(); 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/interrupt/ThreadInterrupt.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread.interrupt; 2 | 3 | /** 4 | * @User krisjin 5 | * @date 2020/8/26 6 | */ 7 | public class ThreadInterrupt { 8 | 9 | public static void main(String[] args) { 10 | try { 11 | TestTask t = new TestTask(); 12 | t.start(); 13 | Thread.sleep(2000); 14 | t.interrupt(); 15 | } catch (InterruptedException e) { 16 | e.printStackTrace(); 17 | } 18 | System.err.println("main end"); 19 | } 20 | 21 | static class TestTask extends Thread { 22 | public void run() { 23 | System.err.println("task execute...."); 24 | try { 25 | while (true) 26 | for (int i = 0; i < 10; i++) { 27 | if (this.isInterrupted()) { 28 | System.err.println("线程停止...."); 29 | throw new InterruptedException(); 30 | } 31 | } 32 | // System.err.println(11); 33 | } catch (InterruptedException e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/interrupt/Write.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread.interrupt; 2 | 3 | public class Write implements Runnable { 4 | private BufferInterruptibly buffer; 5 | 6 | public Write(BufferInterruptibly buffer) { 7 | this.buffer = buffer; 8 | } 9 | 10 | @Override 11 | public void run() { 12 | buffer.write(); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/pool/CompletionServiceTest.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread.pool; 2 | 3 | import org.banyan.concurrent.util.SleepUtil; 4 | 5 | import java.util.concurrent.*; 6 | 7 | /** 8 | * User: krisjin 9 | * Date: 2017/3/7 10 | */ 11 | public class CompletionServiceTest { 12 | 13 | public static void main(String[] args) throws InterruptedException, ExecutionException { 14 | // AtomicInteger count = new AtomicInteger(1); 15 | ExecutorService exec = Executors.newFixedThreadPool(15); 16 | final BlockingQueue> queue = new LinkedBlockingDeque>(); 17 | //实例化CompletionService 18 | final CompletionService completionService = new ExecutorCompletionService(exec, queue); 19 | 20 | 21 | for (int i = 0; i < 10; i++) { 22 | completionService.submit(new Callable() { 23 | @Override 24 | public String call() throws Exception { 25 | SleepUtil.second(2); 26 | System.out.println(Thread.currentThread().getName() + " 休息了 "); 27 | return "Demo1Main"; 28 | } 29 | }); 30 | } 31 | 32 | 33 | for (int i = 0; i < 10; i++) { 34 | try { 35 | //谁最先执行完成,直接返回 36 | Future f = completionService.take(); 37 | System.out.println(f.get()); 38 | } catch (InterruptedException e) { 39 | e.printStackTrace(); 40 | } catch (ExecutionException e) { 41 | e.printStackTrace(); 42 | } 43 | } 44 | 45 | exec.shutdown(); 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/pool/Connection.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread.pool; 2 | 3 | import org.banyan.concurrent.util.SleepUtil; 4 | 5 | /** 6 | * User: krisjin 7 | * Date: 2016/2/17 8 | */ 9 | public class Connection { 10 | public void sendStatement() { 11 | SleepUtil.millisecond(10); 12 | System.out.println(Thread.currentThread().getName() + " send statement."); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/pool/NamedThreadFactory.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread.pool; 2 | 3 | import java.util.concurrent.ThreadFactory; 4 | import java.util.concurrent.atomic.AtomicInteger; 5 | 6 | /** 7 | * 带名称的线程生成工厂,支持设置名称,设置是否为守护线程 8 | */ 9 | public class NamedThreadFactory implements ThreadFactory { 10 | 11 | /** 12 | * 系统全局线程池计数器 13 | */ 14 | private static final AtomicInteger poolCount = new AtomicInteger(); 15 | /** 16 | * 当前线程池计数器 17 | */ 18 | final AtomicInteger threadCount = new AtomicInteger(1); 19 | final ThreadGroup group; 20 | final String namePrefix; 21 | final boolean isDaemon; //是否守护线程,true的话随主线程退出而退出,false的话则要主动退出 22 | 23 | /** 24 | * 构造函数,默认非守护线程 25 | * 26 | * @param prefix 前缀 27 | */ 28 | public NamedThreadFactory(String prefix) { 29 | this(prefix, false); 30 | } 31 | 32 | /** 33 | * 构造函数 34 | * 35 | * @param prefix 前缀,后面会自动加上-SortMain- 36 | * @param daemon 是否守护线程,true的话随主线程退出而退出,false的话则要主动退出 37 | */ 38 | public NamedThreadFactory(String prefix, boolean daemon) { 39 | SecurityManager s = System.getSecurityManager(); 40 | group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); 41 | namePrefix = prefix + "-" + poolCount.getAndIncrement() + "-SortMain-"; 42 | isDaemon = daemon; 43 | } 44 | 45 | @Override 46 | public Thread newThread(Runnable r) { 47 | Thread t = new Thread(group, r, namePrefix + threadCount.getAndIncrement(), 0); 48 | t.setDaemon(isDaemon); 49 | if (t.getPriority() != Thread.NORM_PRIORITY) { 50 | t.setPriority(Thread.NORM_PRIORITY); 51 | } 52 | return t; 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/pool/ThreadPool.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread.pool; 2 | 3 | /** 4 | * User: krisjin 5 | * Date: 2016/2/19 6 | */ 7 | public interface ThreadPool { 8 | 9 | /** 10 | * 执行提交的任务 11 | * 12 | * @param job 13 | */ 14 | public void execute(Job job); 15 | 16 | /** 17 | * 关闭线程池 18 | */ 19 | public void shutdown(); 20 | 21 | /** 22 | * 增加工作线程 23 | * 24 | * @param workersNum 25 | */ 26 | public void addWorkers(int workersNum); 27 | 28 | /** 29 | * 减少工作线程 30 | * 31 | * @param workNum 32 | */ 33 | public void removeWorkers(int workNum); 34 | 35 | public int getJobSize(); 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/pool/thread pool.md: -------------------------------------------------------------------------------- 1 | 合理利用线程池能够带来三个好处。第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。 2 | 第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。第三:提高线程的可管理性。线程是稀缺资源, 3 | 如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。 4 | 但是要做到合理的利用线程池,必须对其原理了如指掌。 -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/readme.md: -------------------------------------------------------------------------------- 1 | # 线程池 2 | java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池。 3 | 在开发中合理的使用线程池能够带来三个好处。 4 | 1. 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。 5 | 2. 提高响应速度。当任务到达时,任务可以不需要等待线程创建就能立即执行。 6 | 3. 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性, 7 | 使用线程池可以进行统一分配、调优和监控。但是,要做到合理利用线程池,必须对其原理了如指掌。 8 | 9 | 10 | 11 | 12 | 并发 -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/search/Client.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread.search; 2 | 3 | import java.io.File; 4 | import java.util.concurrent.BlockingQueue; 5 | import java.util.concurrent.LinkedBlockingQueue; 6 | 7 | /** 8 | *

9 | * User : krisjin 10 | * Date: 2015/4/11 11 | * Time: 14:26 12 | */ 13 | public class Client { 14 | 15 | public static void main(String[] args) { 16 | 17 | //定义一个阻塞队列 18 | BlockingQueue queue = new LinkedBlockingQueue(); 19 | 20 | final int processor = Runtime.getRuntime().availableProcessors() / 2; 21 | File dir = new File("d:/download"); 22 | 23 | Thread crawlThread = new Thread(new CrawlerThread(queue, dir)); 24 | crawlThread.start(); 25 | 26 | for (int i = 0; i < processor; i++) { 27 | new Thread(new IndexThread(queue)).start(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/search/CrawlerThread.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread.search; 2 | 3 | import java.io.File; 4 | import java.util.concurrent.BlockingQueue; 5 | 6 | /** 7 | * 爬虫线程 8 | *

9 | * User : krisjin 10 | * Date: 2015/4/11 11 | * Time: 14:10 12 | */ 13 | public class CrawlerThread implements Runnable { 14 | 15 | private final BlockingQueue fileQueue; 16 | private final File dir; 17 | 18 | public CrawlerThread(BlockingQueue fileQueue, File dir) { 19 | super(); 20 | this.fileQueue = fileQueue; 21 | this.dir = dir; 22 | } 23 | 24 | 25 | private void crawl(File root) throws InterruptedException { 26 | File[] files = root.listFiles(); 27 | if (files != null) { 28 | for (File f : files) { 29 | if (f.isDirectory()) { 30 | crawl(f); 31 | } else if (!fileQueue.contains(f)) { 32 | System.out.println("Crawl file " + f.getAbsoluteFile()); 33 | //阻塞式插入 34 | fileQueue.put(f); 35 | } 36 | } 37 | } 38 | } 39 | 40 | 41 | @Override 42 | public void run() { 43 | try { 44 | crawl(dir); 45 | } catch (InterruptedException e) { 46 | e.printStackTrace(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/search/IndexThread.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread.search; 2 | 3 | import java.io.File; 4 | import java.util.concurrent.BlockingQueue; 5 | 6 | /** 7 | *

8 | * User : krisjin 9 | * Date: 2015/4/11 10 | * Time: 14:21 11 | */ 12 | public class IndexThread implements Runnable { 13 | 14 | private final BlockingQueue queue; 15 | 16 | public IndexThread(BlockingQueue queue) { 17 | super(); 18 | this.queue = queue; 19 | } 20 | 21 | public void run() { 22 | while (true) { 23 | try { 24 | File file = queue.take(); 25 | index(file); 26 | } catch (InterruptedException e) { 27 | e.printStackTrace(); 28 | } 29 | } 30 | } 31 | 32 | private void index(File file) { 33 | System.out.println(Thread.currentThread().getName() + " Index file " + file.getAbsolutePath() + " ..."); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/sleep/SleepTest.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread.sleep; 2 | 3 | import java.util.concurrent.locks.ReentrantLock; 4 | 5 | /** 6 | * User:krisjin 7 | * Date:2019/4/7 8 | *   9 | */ 10 | public class SleepTest { 11 | ReentrantLock lock = new ReentrantLock(); 12 | Thread threadA = new Thread() { 13 | 14 | public void run() { 15 | System.err.println("Thread A start sleep... "); 16 | try { 17 | Thread.sleep(1000); 18 | } catch (InterruptedException e) { 19 | e.printStackTrace(); 20 | } 21 | } 22 | }; 23 | 24 | 25 | Thread threadB = new Thread() { 26 | 27 | public void run() { 28 | System.err.println("Thread B start sleep... "); 29 | try { 30 | Thread.sleep(1000); 31 | } catch (InterruptedException e) { 32 | e.printStackTrace(); 33 | } 34 | } 35 | }; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/thread/waitnotify/EvenOddInWaitNotify.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.thread.waitnotify; 2 | 3 | import lombok.SneakyThrows; 4 | 5 | /** 6 | * User:krisjin 7 | * Date:2019/4/3 8 | */ 9 | public class EvenOddInWaitNotify { 10 | static int num = 1; 11 | static Object lock = new Object(); 12 | 13 | public static void main(String[] args) { 14 | new Thread(new EvenOddInWaitNotify.Even()).start(); 15 | new Thread(new EvenOddInWaitNotify.Odd()).start(); 16 | } 17 | 18 | static class Odd implements Runnable { 19 | @SneakyThrows 20 | public void run() { 21 | synchronized (lock) { 22 | while (num <= 100) { 23 | if (num % 2 != 0) { 24 | System.out.println("奇数:" + num); 25 | ++num; 26 | lock.notify(); 27 | } else { 28 | try { 29 | lock.wait(); 30 | } catch (InterruptedException e) { 31 | e.printStackTrace(); 32 | } 33 | } 34 | } 35 | } 36 | } 37 | } 38 | 39 | static class Even implements Runnable { 40 | @SneakyThrows 41 | public void run() { 42 | synchronized (lock) { 43 | while (num <= 100) { 44 | if (num % 2 == 0) { 45 | System.out.println("偶数:" + num); 46 | ++num; 47 | lock.notify(); 48 | } else { 49 | try { 50 | lock.wait(); 51 | } catch (InterruptedException e) { 52 | e.printStackTrace(); 53 | } 54 | } 55 | } 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/threadlocal/TLExam1.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.threadlocal; 2 | 3 | /** 4 | * User: krisjin 5 | * Date: 2016/2/1 6 | */ 7 | public class TLExam1 { 8 | private static ThreadLocal strThreadLocal = new ThreadLocal<>(); 9 | 10 | public void setPin(String pin) { 11 | strThreadLocal.set(pin + ": " + Thread.currentThread().getId() + ": " + Thread.currentThread().getName()); 12 | } 13 | 14 | public String getPin() { 15 | return strThreadLocal.get(); 16 | } 17 | 18 | public static void main(String[] args) throws InterruptedException { 19 | TLExam1 TLExam1 = new TLExam1(); 20 | TLExam1.setPin("2020"); 21 | 22 | System.out.println(TLExam1.getPin()); 23 | 24 | Thread t1 = new Thread(new MyRunnable(TLExam1)); 25 | t1.start(); 26 | t1.join(); 27 | System.out.println(TLExam1.getPin()); 28 | } 29 | 30 | static class MyRunnable implements Runnable { 31 | TLExam1 TLExam1; 32 | public MyRunnable(TLExam1 TLExam1) { 33 | this.TLExam1 = TLExam1; 34 | } 35 | 36 | public void run() { 37 | TLExam1.setPin("2021"); 38 | System.out.println(TLExam1.getPin()); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/threadlocal/TLExam3.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.threadlocal; 2 | 3 | /** 4 | * @author krisjin 5 | * @date 2020/11/3 6 | */ 7 | public class TLExam3 { 8 | private static ThreadLocal tl = new ThreadLocal<>(); 9 | 10 | public void setVal(String name) { 11 | tl.set(Thread.currentThread().getName() + " -> " + name); 12 | } 13 | 14 | public String get1() { 15 | return tl.get(); 16 | } 17 | 18 | public String get2() { 19 | return tl.get(); 20 | } 21 | 22 | public String get3() { 23 | return tl.get(); 24 | } 25 | 26 | public static void main(String[] args) { 27 | TLExam3 tlExam3 = new TLExam3(); 28 | tlExam3.setVal("tl"); 29 | System.err.println(tlExam3.get1()); 30 | System.err.println(tlExam3.get2()); 31 | System.err.println(tlExam3.get3()); 32 | 33 | //创建子线程 34 | new Thread(new ChildThread(tlExam3)).start(); 35 | } 36 | 37 | static class ChildThread implements Runnable { 38 | private TLExam3 tlExam3; 39 | 40 | public ChildThread(TLExam3 tlExam3) { 41 | this.tlExam3 = tlExam3; 42 | } 43 | 44 | public void run() { 45 | tlExam3.setVal("kris"); 46 | System.err.println(tlExam3.get1()); 47 | System.err.println(tlExam3.get2()); 48 | tlExam3.setVal("kris-2");//重新设值 49 | System.err.println(tlExam3.get3()); 50 | 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/threadlocal/ThreadSafeDateFormat.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.threadlocal; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | /** 7 | * Thread Local Confinement 8 | * Using a thread safe SimpleDateFormat object 9 | */ 10 | public class ThreadSafeDateFormat { 11 | 12 | private static final ThreadLocal threadLocalDateFormat = new ThreadLocal() { 13 | @Override 14 | protected SimpleDateFormat initialValue() { 15 | return new SimpleDateFormat("DD/MM/YYYY HH:mm:ss"); 16 | } 17 | }; 18 | 19 | public String format(Date date) { 20 | return threadLocalDateFormat.get().format(date); 21 | } 22 | 23 | public static void main(String[] args) { 24 | 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/threadpool/FixedThreadPoolScene.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.threadpool; 2 | 3 | 4 | import java.util.*; 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.Executors; 7 | import java.util.concurrent.Future; 8 | 9 | public class FixedThreadPoolScene { 10 | 11 | private ExecutorService fixedPool = Executors.newFixedThreadPool(4); 12 | 13 | public static void main(String[] args) { 14 | FixedThreadPoolScene fixedThreadPoolScene = new FixedThreadPoolScene(); 15 | } 16 | 17 | 18 | public void test1() { 19 | 20 | System.out.println("=== FixedThreadPool ==="); 21 | List> uuids = new LinkedList<>(); 22 | 23 | Map mapParam = new HashMap<>(); 24 | 25 | mapParam.put("pageSize", 10); 26 | mapParam.put("pageNum", 1); 27 | 28 | for (int i = 1; i <= 20; i++) { 29 | mapParam.put("pageNum", i); 30 | Future submitted = fixedPool.submit(() -> { 31 | page(mapParam); 32 | 33 | UUID randomUUID = UUID.randomUUID(); 34 | return randomUUID; 35 | }); 36 | uuids.add(submitted); 37 | } 38 | 39 | 40 | } 41 | 42 | 43 | private void page(Map param) { 44 | Integer pageSize = Integer.valueOf(param.get("pageSize") + ""); 45 | Integer pageNum = Integer.valueOf(param.get("pageNum") + ""); 46 | System.out.println("pageSize=" + pageSize + ",pageNum=" + pageNum); 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/threadpool/PThread.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.threadpool; 2 | 3 | /** 4 | * @author krisjin on 2017/5/19 5 | */ 6 | public class PThread extends Thread { 7 | 8 | private ThreadPool threadPool; 9 | private Runnable target; 10 | private volatile boolean isShutdown = false; 11 | private volatile boolean isIdle = false; 12 | 13 | public PThread(Runnable target, String name, ThreadPool threadPool) { 14 | super(name); 15 | this.threadPool = threadPool; 16 | this.target = target; 17 | } 18 | 19 | public Runnable getTarget() { 20 | return target; 21 | } 22 | 23 | public synchronized void setTarget(Runnable target) { 24 | this.target = target; 25 | //设置了任务之后,通知run方法,开始执行这个任务 26 | notifyAll(); 27 | } 28 | 29 | public boolean isShutdown() { 30 | return isShutdown; 31 | } 32 | 33 | public boolean isIdle() { 34 | return isIdle; 35 | } 36 | 37 | @Override 38 | public void run() { 39 | //只要没有关闭,就一直不结束该线程 40 | while (!isShutdown) { 41 | isIdle = false; 42 | if (target != null) { 43 | target.run(); 44 | } 45 | //任务结束了到闲置状态 46 | isIdle = true; 47 | try { 48 | //任务结束后不关闭线程,而是放入线程池空闲对列 49 | threadPool.add(this); 50 | synchronized (this) { 51 | wait();//thread is idle ,wait new thread 52 | } 53 | } catch (InterruptedException e) { 54 | e.printStackTrace(); 55 | } 56 | isIdle = false; 57 | } 58 | } 59 | 60 | public synchronized void shutdown() { 61 | isShutdown = true; 62 | notifyAll(); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/threadpool/SimParallelThreadPool.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.threadpool; 2 | 3 | import org.banyan.concurrent.thread.pool.NamedThreadFactory; 4 | 5 | import java.util.concurrent.LinkedBlockingQueue; 6 | import java.util.concurrent.ThreadFactory; 7 | import java.util.concurrent.ThreadPoolExecutor; 8 | import java.util.concurrent.TimeUnit; 9 | 10 | public class SimParallelThreadPool { 11 | 12 | public static Integer threadNum = 20; 13 | 14 | public void setThreadNum(Integer threadNum) { 15 | SimParallelThreadPool.threadNum = threadNum; 16 | } 17 | 18 | private static ThreadFactory threadFactory = new NamedThreadFactory("BM25"); 19 | 20 | private static volatile ThreadPoolExecutor threadPoolExecutor = null; 21 | 22 | //Init threadpool 23 | public static ThreadPoolExecutor getThreadPool() { 24 | if (threadPoolExecutor == null) { 25 | synchronized (SimParallelThreadPool.class) { 26 | if (threadPoolExecutor == null) { 27 | threadPoolExecutor = new ThreadPoolExecutor(threadNum, threadNum, 28 | 30L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(5000), threadFactory); 29 | } 30 | } 31 | } 32 | return threadPoolExecutor; 33 | } 34 | 35 | //Shut down threadPool 36 | public void shutDownThreadPool() { 37 | if (threadPoolExecutor != null) { 38 | threadPoolExecutor.shutdown(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/threadpool/SimpleThread.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.threadpool; 2 | 3 | public class SimpleThread implements Runnable { 4 | private String name; 5 | 6 | public SimpleThread(String name) { 7 | this.name = name; 8 | } 9 | 10 | @Override 11 | public void run() { 12 | try { 13 | //业务线程执行时间 14 | Thread.sleep(100); 15 | } catch (InterruptedException e) { 16 | e.printStackTrace(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/concurrent/util/SleepUtil.java: -------------------------------------------------------------------------------- 1 | package org.banyan.concurrent.util; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * 休眠工具类 7 | * User: krisjin 8 | * Date: 2016/2/4 9 | */ 10 | public class SleepUtil { 11 | 12 | /** 13 | * 以秒单位休眠 14 | * 15 | * @param second 16 | */ 17 | public static final void second(long second) { 18 | try { 19 | TimeUnit.SECONDS.sleep(second); 20 | } catch (InterruptedException e) { 21 | e.printStackTrace(); 22 | } 23 | } 24 | 25 | /** 26 | * 以毫秒单位休眠 27 | * 28 | * @param millisecond 29 | */ 30 | public static final void millisecond(long millisecond) { 31 | try { 32 | TimeUnit.MILLISECONDS.sleep(millisecond); 33 | } catch (InterruptedException e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/features/futures/UsingFutureTasks.java: -------------------------------------------------------------------------------- 1 | package org.banyan.features.futures; 2 | 3 | import java.util.Random; 4 | import java.util.concurrent.*; 5 | 6 | /** 7 | * FutureTask represents an asynchronous computation. It has methods to check 8 | * if the computation is completed and to cancel it if needed. 9 | *

10 | * Used for computing long running tasks/IO tasks. 11 | *

12 | * Act as a latch and has three states: waiting for run, running or completed. 13 | * Also, it can be easy canceled with the cancel() method. 14 | *

15 | * if the result is ready, get() will return the value. Otherwise, it'll block. 16 | */ 17 | public class UsingFutureTasks { 18 | 19 | public static void main(String[] args) { 20 | Callable callable = () -> { 21 | int random = new Random().nextInt(10) * 100; 22 | System.out.println("Preparing to execute"); 23 | Thread.sleep(random); 24 | System.out.println("Executed - " + random); 25 | return random; 26 | }; 27 | 28 | FutureTask futureTask = new FutureTask<>(callable); 29 | 30 | ExecutorService executor = Executors.newSingleThreadExecutor(); 31 | executor.execute(futureTask); 32 | 33 | try { 34 | Integer value = futureTask.get(2, TimeUnit.SECONDS); 35 | System.out.println("Value is " + value); 36 | } catch (InterruptedException | ExecutionException | TimeoutException e) { 37 | e.printStackTrace(); 38 | } 39 | executor.shutdown(); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/features/synchronizers/UsingBarriers.java: -------------------------------------------------------------------------------- 1 | package org.banyan.features.synchronizers; 2 | 3 | import java.util.Random; 4 | import java.util.concurrent.BrokenBarrierException; 5 | import java.util.concurrent.CyclicBarrier; 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | 9 | /** 10 | * Barriers are used for blocking a group of threads until they come together at 11 | * a single point in order to proceed. Basically, convergence of threads. 12 | *

13 | * Accepts a runnable in it's constructor to be called when the threads reach the 14 | * barrier, but before its unblocked 15 | *

16 | * Most common implementation is cyclic barrier. 17 | *

18 | * 内存屏障或内存栅栏,也就是让一个CPU处理单元中的内存状态对其它处理单元可见的一项技术。 19 | */ 20 | public class UsingBarriers { 21 | 22 | public static void main(String[] args) { 23 | 24 | ExecutorService executor = Executors.newCachedThreadPool(); 25 | Runnable barrierAction = () -> System.out.println("Well done, guys!"); 26 | 27 | CyclicBarrier barrier = new CyclicBarrier(10, barrierAction); 28 | 29 | Runnable task = () -> { 30 | try { 31 | // simulating a task that can take at most 1sec to run 32 | System.out.println("Doing task for " + Thread.currentThread().getName()); 33 | Thread.sleep(new Random().nextInt(10) * 100); 34 | System.out.println("Done for " + Thread.currentThread().getName()); 35 | barrier.await(); 36 | } catch (InterruptedException | BrokenBarrierException e) { 37 | e.printStackTrace(); 38 | } 39 | }; 40 | 41 | for (int i = 0; i < 10; i++) { 42 | executor.execute(task); 43 | } 44 | executor.shutdown(); 45 | 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/features/synchronizers/UsingLatches.java: -------------------------------------------------------------------------------- 1 | package org.banyan.features.synchronizers; 2 | 3 | import java.util.concurrent.CountDownLatch; 4 | import java.util.concurrent.ExecutorService; 5 | import java.util.concurrent.Executors; 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Latches are used to delay the progress of threads until it reach a terminal 10 | * state 11 | *

12 | * Most common implementation is CountDownLatch. 13 | *

14 | * In CountDownLatch, each event adds 1. When ready, countDown() is called, 15 | * decrementing by counter by 1. await() method releases when counter is 0. 16 | *

17 | * Single use synchronizer. 18 | */ 19 | public class UsingLatches { 20 | 21 | public static void main(String[] args) { 22 | ExecutorService executor = Executors.newCachedThreadPool(); 23 | CountDownLatch latch = new CountDownLatch(3); 24 | Runnable r = () -> { 25 | try { 26 | Thread.sleep(1000); 27 | System.out.println("Service in " + Thread.currentThread().getName() + " initialized."); 28 | latch.countDown(); 29 | } catch (InterruptedException e) { 30 | e.printStackTrace(); 31 | } 32 | }; 33 | executor.execute(r); 34 | executor.execute(r); 35 | executor.execute(r); 36 | try { 37 | latch.await(2, TimeUnit.SECONDS); 38 | System.out.println("All services up and running!"); 39 | } catch (InterruptedException e) { 40 | e.printStackTrace(); 41 | } 42 | executor.shutdown(); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/features/synchronizers/UsingSemaphores.java: -------------------------------------------------------------------------------- 1 | package org.banyan.features.synchronizers; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | import java.util.concurrent.Semaphore; 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Semaphores controls the number of activities that can access a resource or 10 | * perform a certain action; 11 | *

12 | * - First you give a number of 'permits'; 13 | *

14 | * - Activities will acquire it and release when they're done; 15 | *

16 | * - If none is available, activity will block until one become available. 17 | *

18 | * Good for resource pools. 19 | */ 20 | public class UsingSemaphores { 21 | public static void main(String[] args) { 22 | ExecutorService executor = Executors.newCachedThreadPool(); 23 | Semaphore semaphore = new Semaphore(3); 24 | 25 | Runnable r = () -> { 26 | try { 27 | System.out.println("Trying to acquire - " + Thread.currentThread().getName()); 28 | if (semaphore.tryAcquire(2, TimeUnit.SECONDS)) { 29 | // use-get resource 30 | // simulate work in progress 31 | System.out.println("Acquired - " + Thread.currentThread().getName()); 32 | Thread.sleep(2000); 33 | System.out.println("Done - " + Thread.currentThread().getName()); 34 | } 35 | } catch (InterruptedException e) { 36 | e.printStackTrace(); 37 | } finally { 38 | semaphore.release(); 39 | } 40 | }; 41 | for (int i = 0; i < 4; i++) { 42 | executor.execute(r); 43 | } 44 | 45 | executor.shutdown(); 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/features/threads/Test.java: -------------------------------------------------------------------------------- 1 | package org.banyan.features.threads; 2 | 3 | /** 4 | * @author kris 5 | * @date 2023/12/22 6 | */ 7 | public class Test { 8 | 9 | 10 | public static void main(String[] args) { 11 | Thread thread = new Thread(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/features/threads/UsingThreads.java: -------------------------------------------------------------------------------- 1 | package org.banyan.features.threads; 2 | 3 | /** 4 | * Threads 5 | *

6 | * Java support for OS-threads. 7 | *

8 | * Thread is a basic unit that can run in parallel through CPU cores. 9 | *

10 | * A thread can 'see' others threads memory. 11 | */ 12 | public class UsingThreads { 13 | 14 | public static void main(String[] args) throws InterruptedException { 15 | // Creating 16 | Thread created = new Thread(); 17 | created.start(); 18 | // .run() runs on main thread 19 | 20 | // Assigning a task for running on a thread - we pass a Runnable instance 21 | Thread threadWithTask = new Thread(() -> System.out.println("Inside thread" + Thread.currentThread().getName())); 22 | threadWithTask.start(); 23 | 24 | // Interrupting a thread 25 | Runnable interrupatblyTask = () -> { 26 | while (!Thread.currentThread().isInterrupted()) { 27 | System.out.println("Im not interrupted " + Thread.currentThread().getName()); 28 | } 29 | }; 30 | Thread interruptable = new Thread(interrupatblyTask); 31 | interruptable.start(); 32 | Thread.sleep(3000); 33 | interruptable.interrupt(); 34 | 35 | } 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/GuardedBy.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(value = {ElementType.FIELD, ElementType.METHOD}) 9 | @Retention(RetentionPolicy.CLASS) 10 | public @interface GuardedBy { 11 | String value(); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/ThreadSafe.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(value = {ElementType.TYPE}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface ThreadSafe { 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/fixed_lock_ordering/FixedLockOrdering.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns.fixed_lock_ordering; 2 | 3 | /** 4 | * Pattern: Fixed Lock Ordering 5 | *

6 | * Motivations: Acquiring locks in a non fixed-order can deadlock if they're called at the 7 | * same time, but with the inverse order. 8 | *

9 | * Intent: Create a fixed-ordered locking mechanism to prevent possibles 10 | * deadlocks. We define a value to the locks objects and use comparisons to 11 | * establish a fixed order bases on who is greater or lesser. 12 | *

13 | * Applicability: Every time when acquiring more than one lock. 14 | */ 15 | public class FixedLockOrdering { 16 | 17 | static class LockableObject { 18 | private int id; 19 | private String anotherValue; 20 | 21 | public int getId() { 22 | return id; 23 | } 24 | 25 | public void setId(int id) { 26 | this.id = id; 27 | } 28 | 29 | public String getAnotherValue() { 30 | return anotherValue; 31 | } 32 | 33 | public void setAnotherValue(String anotherValue) { 34 | this.anotherValue = anotherValue; 35 | } 36 | 37 | } 38 | 39 | public void doSomeOperation(LockableObject obj1, LockableObject obj2) { 40 | int obj1Id = obj1.getId(); 41 | int obj2Id = obj2.getId(); 42 | if (obj1Id < obj2Id) { 43 | synchronized (obj1) { 44 | synchronized (obj2) { 45 | // action 46 | } 47 | } 48 | } else { 49 | synchronized (obj2) { 50 | synchronized (obj1) { 51 | // action 52 | } 53 | } 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/non_blocking/DoubleCounter.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns.non_blocking; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | /** 6 | * Pattern: Non-blocking Design 7 | *

8 | * Example: Double Counter 9 | */ 10 | public class DoubleCounter { 11 | 12 | private AtomicInteger value = new AtomicInteger(0); 13 | 14 | public void increase() { 15 | int updatedValue; 16 | int old; 17 | do { 18 | old = value.get(); // get value 19 | updatedValue = old + 2; // new updated value 20 | } while (!value.compareAndSet(old, updatedValue)); 21 | /* 22 | * if the expected value (old) differs from what is actually present in the 23 | * structure, this means that in the mean time some thread changed it. The loop 24 | * will run again until it reaches an acceptable state. 25 | */ 26 | } 27 | 28 | public int getValue() { 29 | return value.get(); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/non_blocking/NonBlockingDesign.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns.non_blocking; 2 | 3 | import java.util.concurrent.atomic.AtomicReference; 4 | 5 | /** 6 | * Pattern: Non-blocking Design 7 | *

8 | * Motivations: Blocking algorithms are inefficiently under certain loads and are 9 | * susceptible to failures like liveness. Algorithms are called non-blocking if 10 | * failure or suspension of any thread cannot cause the suspension or failure of 11 | * another thread; or if in each step it can make progress in some thread. 12 | *

13 | * Intent: Non-blocking algorithms actually can block briefly, by limiting the 14 | * scope of atomic changes to a single variable while maintaining data 15 | * consistency. 16 | *

17 | * Applicability: Performance dependent operations where blocking designs can be 18 | * a problem. 19 | */ 20 | public class NonBlockingDesign { 21 | 22 | private AtomicReference value = new AtomicReference<>(new Object()); 23 | 24 | public void modifyValue() { 25 | Object updatedValue; 26 | Object old; 27 | do { 28 | old = value.get(); // get value 29 | updatedValue = new Object(); // new updated value 30 | } while (!value.compareAndSet(old, updatedValue)); 31 | /* 32 | * if the expected value (old) differs from what is actually present in the 33 | * structure, this means that in the mean time some thread changed it. The loop 34 | * will run until it reaches an acceptable state. 35 | */ 36 | } 37 | 38 | public Object getValue() { 39 | return value.get(); 40 | } 41 | 42 | /* 43 | * Modified value... 44 | */ 45 | public Object newObject() { 46 | return new Object(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/resource_pool/ResourcePool.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns.resource_pool; 2 | 3 | import java.util.List; 4 | import java.util.concurrent.BlockingQueue; 5 | import java.util.concurrent.LinkedBlockingQueue; 6 | import java.util.concurrent.Semaphore; 7 | import java.util.concurrent.TimeUnit; 8 | 9 | /** 10 | * Pattern: Resource Pool 11 | *

12 | * Motivations: Some resources can be limited, and it's import to ensures those 13 | * limits in concurrent programming. 14 | *

15 | * Intent: Establish a mechanism for limiting the resource use. It'll block the 16 | * user when there's none available. It Implements the concurrent thread-safe 17 | * pool using Semaphores. 18 | *

19 | * Applicability: Use when you want to create a pool of some limited resource. 20 | */ 21 | public class ResourcePool { 22 | 23 | private final static TimeUnit TIME_UNIT = TimeUnit.SECONDS; 24 | private Semaphore semaphore; 25 | private BlockingQueue resources; 26 | 27 | public ResourcePool(int poolSize, List initializedResources) { 28 | this.semaphore = new Semaphore(poolSize, true); 29 | this.resources = new LinkedBlockingQueue<>(poolSize); 30 | this.resources.addAll(initializedResources); 31 | } 32 | 33 | public T get() throws InterruptedException { 34 | return get(Integer.MAX_VALUE); 35 | } 36 | 37 | public T get(long secondsToTimeout) throws InterruptedException { 38 | semaphore.acquire(); 39 | try { 40 | T resource = resources.poll(secondsToTimeout, TIME_UNIT); 41 | return resource; 42 | } finally { 43 | semaphore.release(); 44 | } 45 | } 46 | 47 | public void release(T resource) throws InterruptedException { 48 | if (resource != null) { 49 | resources.put(resource); 50 | semaphore.release(); 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/resource_pool/ResourcePoolUsage.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns.resource_pool; 2 | 3 | import java.util.Arrays; 4 | import java.util.Random; 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.Executors; 7 | 8 | /** 9 | * Pattern: Resource Pool 10 | *

11 | * Example: Resource Pool usage 12 | */ 13 | public class ResourcePoolUsage { 14 | public static void main(String[] args) { 15 | ExecutorService executor = Executors.newCachedThreadPool(); 16 | ResourcePool pool = new ResourcePool<>(15, 17 | Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12, 13, 14)); 18 | Random r = new Random(); 19 | for (int i = 0; i < 30; i++) { 20 | executor.execute(() -> { 21 | try { 22 | Integer value = pool.get(60); 23 | System.out.println("Value taken: " + value); 24 | Thread.sleep(r.nextInt(5000)); 25 | pool.release(value); 26 | System.out.println("Value released " + value); 27 | } catch (InterruptedException e) { 28 | e.printStackTrace(); 29 | } 30 | }); 31 | } 32 | executor.shutdown(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/task_cancel/BackgroundTimePrintTask.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns.task_cancel; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | /** 7 | * Pattern: Thread Task Cancel 8 | *

9 | * Example: Canceling a Background Timer Print Task. 10 | */ 11 | public class BackgroundTimePrintTask { 12 | 13 | private Thread thread; 14 | private Runnable task = () -> { 15 | while (!Thread.currentThread().isInterrupted()) { 16 | Date date = new Date(System.currentTimeMillis()); 17 | System.out.println(new SimpleDateFormat().format(date)); 18 | try { 19 | Thread.sleep(1000); 20 | } catch (InterruptedException e) { 21 | // no need to interrupt() if you don't have anything throwing InterruptedException 22 | thread.interrupt(); 23 | } 24 | } 25 | }; 26 | 27 | public void run() { 28 | thread = new Thread(task); 29 | thread.start(); 30 | } 31 | 32 | public void cancel() { 33 | if (thread != null) { 34 | thread.interrupt(); 35 | } 36 | } 37 | 38 | public static void main(String[] args) { 39 | BackgroundTimePrintTask bttt = new BackgroundTimePrintTask(); 40 | bttt.run(); 41 | try { 42 | Thread.sleep(4000); 43 | } catch (InterruptedException e) { 44 | e.printStackTrace(); 45 | } 46 | bttt.cancel(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/task_cancel/ThreadTaskCancel.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns.task_cancel; 2 | 3 | /** 4 | * Pattern: Thread Task Cancel 5 | *

6 | * Motivations: Tasks that offers a cancel option are common in programming. 7 | * Background tasks, implemented by threads, are common in Java too and often 8 | * they need to be canceled. 9 | *

10 | * Intent: Show how to create a cancel mechanism using threads. Inside the 11 | * Runnable code, we use Thread.currentThread().isInterrupted() to identify the 12 | * thread state and to keep it running or not. 13 | *

14 | * Applicability: When background tasks needs a cancel option. 15 | */ 16 | public class ThreadTaskCancel { 17 | 18 | private Thread thread; 19 | private Runnable task = () -> { 20 | while (!Thread.currentThread().isInterrupted()) { 21 | // keep going 22 | } 23 | }; 24 | 25 | public void run() { 26 | thread = new Thread(task); 27 | thread.start(); 28 | } 29 | 30 | public void cancel() { 31 | if (thread != null) { 32 | thread.interrupt(); 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/thread_safe/DateUtil.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns.thread_safe; 2 | 3 | import java.time.LocalDate; 4 | import java.time.LocalDateTime; 5 | 6 | /** 7 | * @author kris 8 | * @date 2023/11/30 9 | */ 10 | public class DateUtil { 11 | 12 | public static void main(String[] args) { 13 | 14 | LocalDate date = LocalDate.of(2023, 11, 29); 15 | 16 | LocalDate date3 = null; 17 | LocalDateTime date1 = LocalDateTime.of(2023, 11, 30, 23, 55, 0); 18 | 19 | System.err.println(11111); 20 | 21 | if (date.isBefore(date1.toLocalDate()) ) { 22 | System.err.println(11); 23 | } 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/thread_safe/compound_actions/AtomicCompoundActions.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns.thread_safe.compound_actions; 2 | 3 | 4 | import org.banyan.patterns.GuardedBy; 5 | import org.banyan.patterns.ThreadSafe; 6 | 7 | /** 8 | * Pattern: Atomic Compound Actions 9 | *

10 | * Motivations: Compounded actions are actions that depends on a sequence of 11 | * events. They need to be executed atomically as a single unit which totally 12 | * fails or complete. check-then-act, read-modify-write and compare-and-swap are 13 | * common idioms in concurrent programming that can cause race conditions if not 14 | * treated right. 15 | *

16 | * Intent: Prevent race condition issues while using intrinsic locking 17 | * mechanisms when executing compound actions; protect every path where the 18 | * involved variables are used. 19 | *

20 | * Applicability: read-modify-write (i++ operator), check-then-act (lazy 21 | * initialization, singleton), compare-and-swap (Stacks). 22 | */ 23 | @ThreadSafe 24 | public class AtomicCompoundActions { 25 | 26 | @GuardedBy("this") 27 | private Object value; 28 | 29 | // example 30 | public synchronized void checkThenAct() { 31 | if (value != null) { // check 32 | dependentAction(); // if true then-act 33 | } 34 | } 35 | 36 | public void dependentAction() { 37 | } 38 | 39 | public synchronized void getValue() { 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/thread_safe/compound_actions/CompareAndSwapUtil.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns.thread_safe.compound_actions; 2 | 3 | /** 4 | * Pattern: Atomic Compound Actions 5 | *

6 | * Example: Simple Atomic Compound Actions using Compare-and-swap idiom 7 | */ 8 | public class CompareAndSwapUtil { 9 | 10 | private int value; 11 | 12 | public synchronized int getValue() { 13 | return value; 14 | } 15 | 16 | public synchronized int compareAndSwap(int expected, int newValue) { 17 | int old = value; 18 | if (old == expected) { 19 | value = newValue; 20 | } 21 | return old; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/thread_safe/immutable_object/EventKeeper.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns.thread_safe.immutable_object; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * Pattern: Immutable Object with Volatile Reference 7 | *

8 | * Example: Event keeper 9 | */ 10 | public class EventKeeper { 11 | 12 | private volatile Event lastEvent = new Event(null, null, null, null, null); 13 | 14 | public void acceptEvent(String name, String type, String username, byte[] payload) { 15 | switch (type) { 16 | case "STORAGE": 17 | lastEvent = new Event(UUID.randomUUID().toString(), name, type, username, payload); 18 | break; 19 | default: 20 | break; 21 | } 22 | } 23 | 24 | public Event getLastEvent() { 25 | return lastEvent; 26 | } 27 | 28 | static final class Event { 29 | private final String id; 30 | private final String name; 31 | private final String type; 32 | private final String username; 33 | private final byte[] payload; 34 | 35 | public Event(String id, String name, String type, String username, byte[] payload) { 36 | super(); 37 | this.id = id; 38 | this.name = name; 39 | this.type = type; 40 | this.username = username; 41 | this.payload = payload; 42 | } 43 | 44 | public String getId() { 45 | return id; 46 | } 47 | 48 | public String getName() { 49 | return name; 50 | } 51 | 52 | public String getType() { 53 | return type; 54 | } 55 | 56 | public String getUsername() { 57 | return username; 58 | } 59 | 60 | public byte[] getPayload() { 61 | return payload; 62 | } 63 | 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/thread_safe/initialization/SafeInitializationHolder.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns.thread_safe.initialization; 2 | 3 | /** 4 | * Pattern: Safe Lazy Initialization 5 | *

6 | * Motivations: Due to the Java Memory Model, some lazy initialization patterns can be unsafe. 7 | * Apply the Lazy Initialization idiom correctly using the mechanisms provided 8 | * by the JVM. 9 | *

10 | * Intent: Safe initialize our object using the holder idiom. Memory 11 | * writes made during static initialization are automatically visible to all 12 | * threads. 13 | *

14 | * Applicability: Always when you want to initialize an object in a concurrent code 15 | * execution. 16 | */ 17 | public class SafeInitializationHolder { 18 | private static class ResourceHolder { 19 | public static Object resource = new Object(); 20 | } 21 | 22 | public static Object getResource() { 23 | return ResourceHolder.resource; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/thread_safe/publishing/SafePublishing.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns.thread_safe.publishing; 2 | 3 | /** 4 | * Pattern: Safe Publishing 5 | *

6 | * Motivations: If we want to share an object across threads, we must do this 7 | * safely. Publishing an object is making it visible to other parts of the code, 8 | * outside the current scope, showing the reference to it. If not made properly, 9 | * the published object can be in an inconsistent state due to the Java Memory 10 | * Model. 11 | *

12 | * Intent: Publish an object safely, both the reference to the object and the 13 | * object state must be made visible to other threads at the same time. In this 14 | * example, we're using static fields, but AtomicReference, Volatile and Final Fields can also 15 | * an option. 16 | *

17 | * Applicability: Always when you want to make an object visible to other in a 18 | * concurrent code execution. 19 | */ 20 | public class SafePublishing { 21 | 22 | public static Object object; 23 | 24 | { 25 | // use static field or a static block to initialize 26 | // static initialization is safe because it's done automatically locked. 27 | object = new Object(); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/thread_safe/shared_state/ProtectedSharedState.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns.thread_safe.shared_state; 2 | 3 | 4 | import org.banyan.patterns.GuardedBy; 5 | import org.banyan.patterns.ThreadSafe; 6 | 7 | /** 8 | * Pattern: Protected Shared State 9 | *

10 | * Motivations: When you have a shared object passed through threads, you need 11 | * to protect it's internal state. 12 | *

13 | * Intent: Guard the shared mutable state of the object with a lock using the 14 | * synchronized mechanism. Protect all paths that interacts with the object 15 | * state, creating a thread safe class. We do this to avoid hazards like race 16 | * conditions. 17 | *

18 | * Applicability: Simples classes where you have a single independent mutable 19 | * variable(s). 20 | *

21 | * Example: A simple counter class 22 | */ 23 | @ThreadSafe 24 | public class ProtectedSharedState { 25 | 26 | @GuardedBy("this") 27 | private Object state; 28 | 29 | @GuardedBy("this") 30 | private Object state2; 31 | 32 | public synchronized Object getState() { 33 | return state; 34 | } 35 | 36 | public synchronized void setState(Object state) { 37 | this.state = state; 38 | } 39 | 40 | public synchronized Object getState2() { 41 | return state2; 42 | } 43 | 44 | public synchronized void setState2(Object state2) { 45 | this.state2 = state2; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/thread_safe/shared_state/VisitCounter.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns.thread_safe.shared_state; 2 | 3 | 4 | import org.banyan.patterns.GuardedBy; 5 | import org.banyan.patterns.ThreadSafe; 6 | 7 | import java.util.concurrent.ExecutorService; 8 | import java.util.concurrent.Executors; 9 | 10 | /** 11 | * Pattern: Protected Shared State 12 | *

13 | * Example: A simple Counter example. 14 | */ 15 | @ThreadSafe 16 | public class VisitCounter { 17 | 18 | @GuardedBy("this") 19 | private int value; 20 | 21 | public synchronized int actualValue() { 22 | return value; 23 | } 24 | 25 | public synchronized void increase() { 26 | value++; 27 | } 28 | 29 | public synchronized void decrease() { 30 | value--; 31 | } 32 | 33 | public static void main(String[] args) { 34 | VisitCounter counter = new VisitCounter(); 35 | ExecutorService threadPool = Executors.newCachedThreadPool(); 36 | for (int i = 1; i <= 50; i++) { 37 | System.out.println("value " + counter.actualValue() + " i " + i); 38 | threadPool.execute(() -> counter.increase()); 39 | } 40 | threadPool.shutdown(); 41 | System.out.println(counter.actualValue()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/thread_safe/thread_confinement/ThreadLocalConfinement.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns.thread_safe.thread_confinement; 2 | 3 | /** 4 | * Pattern: Thread Local Confinement 5 | *

6 | * Motivation: Dealing with non thread-safe objects is a common situation, and 7 | * it's possible to still have a thread-safe code even using non thread-safe 8 | * classes. 9 | *

10 | * Intent: Use ThreadLocal to confine instances in a per-thread model, keeping a 11 | * object copy to each thread. 12 | *

13 | * Applicability: Use for non thread-safe objects that needs to be shared across threads. 14 | */ 15 | public class ThreadLocalConfinement { 16 | 17 | private static final ThreadLocal threadLocalOject = new ThreadLocal() { 18 | @Override 19 | protected Object initialValue() { 20 | return new Object(); 21 | } 22 | }; 23 | 24 | public Object getNowThreadSafeObjectInstance() { 25 | return threadLocalOject.get(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/banyan/patterns/thread_safe/thread_confinement/ThreadSafeDateFormat.java: -------------------------------------------------------------------------------- 1 | package org.banyan.patterns.thread_safe.thread_confinement; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | /** 7 | * Pattern: Thread Local Confinement 8 | *

9 | * Example: Using a thread safe SimpleDateFormat object 10 | */ 11 | public class ThreadSafeDateFormat { 12 | 13 | private static final ThreadLocal threadLocalDateFormat = new ThreadLocal() { 14 | @Override 15 | protected SimpleDateFormat initialValue() { 16 | return new SimpleDateFormat("DD/MM/YYYY HH:mm:ss"); 17 | } 18 | }; 19 | 20 | public String format(Date date) { 21 | return threadLocalDateFormat.get().format(date); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/resources/diagram/AtomicInteger.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krisjin/banyan/1762f3b26ce8ff0e451d9bc3b30958226f0679cb/src/main/resources/diagram/AtomicInteger.md -------------------------------------------------------------------------------- /src/main/resources/diagram/aaaef'.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krisjin/banyan/1762f3b26ce8ff0e451d9bc3b30958226f0679cb/src/main/resources/diagram/aaaef'.graffle -------------------------------------------------------------------------------- /src/main/resources/diagram/arch_total.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krisjin/banyan/1762f3b26ce8ff0e451d9bc3b30958226f0679cb/src/main/resources/diagram/arch_total.png -------------------------------------------------------------------------------- /src/main/resources/diagram/concurrency-parallel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krisjin/banyan/1762f3b26ce8ff0e451d9bc3b30958226f0679cb/src/main/resources/diagram/concurrency-parallel.jpg -------------------------------------------------------------------------------- /src/main/resources/diagram/future1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krisjin/banyan/1762f3b26ce8ff0e451d9bc3b30958226f0679cb/src/main/resources/diagram/future1.png -------------------------------------------------------------------------------- /src/main/resources/diagram/master-worker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krisjin/banyan/1762f3b26ce8ff0e451d9bc3b30958226f0679cb/src/main/resources/diagram/master-worker.png -------------------------------------------------------------------------------- /src/main/resources/diagram/os_progress_thread.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krisjin/banyan/1762f3b26ce8ff0e451d9bc3b30958226f0679cb/src/main/resources/diagram/os_progress_thread.graffle -------------------------------------------------------------------------------- /src/main/resources/diagram/如何看待对象是否有用.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krisjin/banyan/1762f3b26ce8ff0e451d9bc3b30958226f0679cb/src/main/resources/diagram/如何看待对象是否有用.png -------------------------------------------------------------------------------- /src/main/resources/md/C001.md: -------------------------------------------------------------------------------- 1 | # 并发的风险 2 | 3 | ## 饥饿和死锁 4 | 5 | 线程是很容易陷入饥饿状态的,例如某一程序正准备执行一个关键任务,但执行该任务之前需要先得到用户的确认,而此时正赶上用户在吃饭 6 | 。所以当用户吃的正香的时候,可怜的应用程序就陷入了饥饿的状态。当一个线程等待某个需要运行很长时间或永远无法完成的事件发生时,该 7 | 线程就会陷入饥饿。饥饿的情况可能出现在线程等待用户输入时、等待某些外部事件发生时或等待其它线程释放某个锁时,当线程陷入这种状态 8 | 时,虽然其本身还是活着的,但却什么活也做不了。为了避免线程陷入这种状态,我们可以为其设计一个等待超时但策略,让线程等待有限的 9 | 时间。超出了等待的时间,则该线程将跳出等待状态并在执行完超时逻辑后再继续执行。 10 | 11 | 死锁则是两个或多个线程互相等待对方释放所占用的资源或执行某些动作。 -------------------------------------------------------------------------------- /src/main/resources/md/concurrent_understand.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krisjin/banyan/1762f3b26ce8ff0e451d9bc3b30958226f0679cb/src/main/resources/md/concurrent_understand.md -------------------------------------------------------------------------------- /src/main/resources/md/protocol.md: -------------------------------------------------------------------------------- 1 | 计算机之间的通信规则 2 | 3 | 目前使用的大多数是socket套接字通信方式 -------------------------------------------------------------------------------- /src/main/resources/md/reentrantlock.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krisjin/banyan/1762f3b26ce8ff0e451d9bc3b30958226f0679cb/src/main/resources/md/reentrantlock.md -------------------------------------------------------------------------------- /src/main/resources/md/sleep_yield.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## sleep与yield的区别 4 | 5 | 当线程调用sleep方法时,调用线程会阻塞挂起指定的时间,在这期间线程调度器不会去调度该线程。而调用yield方法时,线程只是让出剩余的时间片,并 6 | 没有被阻塞挂起,而是处于就绪状态,线程调度器下一次调度时就有可能调度到当前线程执行。 -------------------------------------------------------------------------------- /src/main/resources/md/synchronzied.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## 锁的作用域 5 | 6 | - 1.普通方法,锁的范围是当前实例对象 7 | - 2.静态方法,锁的是class的所有同步 8 | 9 | 10 | 11 | 12 | ## synchronized 与 volatile的区别 13 | 14 | - 关键字volatile是线程同步的轻量级实现,性能比synchronized要好,并且volatile只能修饰变量, 15 | 而synchronized可以修饰方法以及代码块。随着jdk版本的升级,synchronized关键字在执行效率 16 | 上得到了很大的提升,在开发中使用synchronized的比率还是比较大的。 17 | 18 | - 多线程访问volatile不会发生阻塞,而synchronized会发生阻塞。 19 | 20 | - volatile能保线程的可见性,但不能保证原子性;而synchronized可以保证原子性,也可以保证可见性, 21 | 因为他会将私有内存和公共内存中的数据做同步。 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 参考: 31 | 32 | https://www.jianshu.com/p/73b9a8466b9c 33 | 34 | 35 | https://crossoverjie.top/2018/05/24/netty/Netty(1)TCP-Heartbeat/ -------------------------------------------------------------------------------- /src/main/resources/md/thread-safe.md: -------------------------------------------------------------------------------- 1 | ## 线程安全性 2 | 3 | 4 | ### 如何保证线程安全 5 | 6 | 1. 方法内变量不存在非线程安全问题,永远都是线程安全的,这是因为方法内部的变量是私有的。 7 | 2. 在写代码时注意下单例中的实例变量的安全性问题,是否线程安全 -------------------------------------------------------------------------------- /src/main/resources/md/threadpoll.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krisjin/banyan/1762f3b26ce8ff0e451d9bc3b30958226f0679cb/src/main/resources/md/threadpoll.md -------------------------------------------------------------------------------- /src/main/resources/md/volatile.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 作用 4 | 保证变量对所有的线程的可见性,当一个线程修改了这个变量的值,其他线程可以立即知道这个新值(之所以有可见性的问题,是因为java的内存模型) 5 | 6 | ## 原理 7 | 8 | 所有变量都存在主内存,每条线程有自己的工作内存,工作内存保存了被该线程使用的变量的主内存副本拷贝 9 | 线程对变量的所有操作都必须在工作内存中进行,不能直接读写主内存的变量,也就是必须先通过工作内存 10 | 一个线程不能访问另一个线程的工作内存 11 | volatile保证了变量更新的时候能够立即同步到主内存,使用变量的时候能立即从主内存刷新到工作内存,这样就保证了变量的可见性 12 | 实际上是通过内存屏障来实现的。语义上,内存屏障之前的所有写操作都要写入内存;内存屏障之后的读操作都可以获得同步屏障之前的写操作的结果。 13 | 14 | ![](https://images2017.cnblogs.com/blog/900751/201708/900751-20170809175926042-624326373.jpg) -------------------------------------------------------------------------------- /src/main/resources/md/并发设计原理.md: -------------------------------------------------------------------------------- 1 | ## 概述 2 | 计算机系统的用户总是希望自己的系统具有更好的性能。他们想要获得质量更高的视频,更好的视觉游戏、更好的网络 3 | 性能。几年前提高处理器的速度可以为用户提供更好的性能。但是如今, -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/ConcurrencyTest.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test; 2 | 3 | /** 4 | * 多线程一定快吗 5 | */ 6 | public class ConcurrencyTest { 7 | 8 | private static final long count = 100001; 9 | public static void main(String[] args) throws InterruptedException { 10 | concurrency(); 11 | serial(); 12 | } 13 | 14 | private static void concurrency() throws InterruptedException { 15 | long start = System.currentTimeMillis(); 16 | 17 | Thread thread = new Thread(new Runnable() { 18 | @Override 19 | public void run() { 20 | long a = 0; 21 | for (long i = 0; i < count; i++) { 22 | a += 5; 23 | } 24 | } 25 | }); 26 | 27 | thread.start(); 28 | long b = 0; 29 | for (long i = 0; i < count; i++) { 30 | b--; 31 | } 32 | thread.join(); 33 | long time = System.currentTimeMillis() - start; 34 | System.out.println("concurrency :" + time + "ms,b=" + b); 35 | } 36 | 37 | private static void serial() { 38 | 39 | long start = System.currentTimeMillis(); 40 | long a = 0; 41 | for (long i = 0; i < count; i++) { 42 | a += 5; 43 | } 44 | long b = 0; 45 | for (long i = 0; i < count; i++) { 46 | b--; 47 | } 48 | long time = System.currentTimeMillis() - start; 49 | System.out.println("serial :" + time + "ms,b=" + b + ",a=" + a); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/Daemon.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | 5 | import java.text.SimpleDateFormat; 6 | import java.util.Date; 7 | import java.util.Map; 8 | 9 | /** 10 | * User : krisjin 11 | * Date: 2015/10/16 12 | */ 13 | public class Daemon { 14 | 15 | public static void main(String[] args) { 16 | Thread t = new Thread(new DaemonRunner()); 17 | t.setDaemon(true); 18 | t.setPriority(10); 19 | t.setName("Daemon thread"); 20 | t.start(); 21 | 22 | 23 | String s = "27*135"; 24 | 25 | s = s.substring(s.lastIndexOf("*")); 26 | 27 | System.err.println(s); 28 | 29 | 30 | System.out.println(2 & 2); 31 | 32 | 33 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:MM:ss"); 34 | 35 | Date d = new Date(); 36 | d.setTime(1565026201127l); 37 | 38 | 39 | System.out.println(sdf.format(d)); 40 | 41 | 42 | System.out.println("--" + (4 & 124)); 43 | 44 | String def = "{\"posid\":\"*6055*24777\",\"matid\":\"轮播banner**\",\"pagid\":\"1\",\"resdata\":{\"cre_id\":\"\",\"rs_id\":\"mc-mkt-cms*6055#24777\",\"res_id\":\"565*4121\",\"str_id\":\"\"},\"ordid\":\"*10*0-0\"}"; 45 | 46 | 47 | Map e = JSONObject.parseObject(def, Map.class); 48 | Map m = (Map) e.get("resdata"); 49 | 50 | System.err.println(m.get("res_id")); 51 | } 52 | 53 | static class DaemonRunner implements Runnable { 54 | 55 | @Override 56 | public void run() { 57 | try { 58 | Thread.sleep(2000); 59 | } catch (InterruptedException e) { 60 | e.printStackTrace(); 61 | } finally { 62 | System.out.println("Daemon thread run."); 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/DateTimePerformanceTest.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test; 2 | 3 | 4 | import java.util.ArrayList; 5 | import java.util.Date; 6 | import java.util.List; 7 | 8 | /** 9 | * User: krisjin 10 | * Date: 2016/10/21 11 | */ 12 | public class DateTimePerformanceTest { 13 | 14 | public void test() { 15 | long time = System.nanoTime(); 16 | long timeTest = System.currentTimeMillis(); 17 | System.out.println(System.nanoTime() - time); 18 | 19 | time = System.nanoTime(); 20 | Date date = new Date(); 21 | System.out.println(System.nanoTime() - time); 22 | 23 | time = System.nanoTime(); 24 | Object object = new Object(); 25 | System.out.println(System.nanoTime() - time); 26 | 27 | time = System.nanoTime(); 28 | List list = new ArrayList(); 29 | System.out.println(System.nanoTime() - time); 30 | 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/EnumStaticMethod.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * User: krisjin 8 | * Date: 2016/2/22 9 | */ 10 | public enum EnumStaticMethod { 11 | PC(1, "PC"), 12 | MOBILE(2, "MOBILE"); 13 | 14 | private int key; 15 | private String value; 16 | 17 | EnumStaticMethod(int key, String value) { 18 | this.key = key; 19 | this.value = value; 20 | } 21 | 22 | public static Map getEnumMap() { 23 | Map enumMap = new HashMap(); 24 | EnumStaticMethod[] enumStaticMethods = EnumStaticMethod.values(); 25 | for (EnumStaticMethod enumStaticMethod : enumStaticMethods) { 26 | enumMap.put(enumStaticMethod.getKey(), enumStaticMethod.getValue()); 27 | } 28 | return enumMap; 29 | } 30 | 31 | public int getKey() { 32 | return key; 33 | } 34 | 35 | public String getValue() { 36 | return value; 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/GenericServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test; 2 | 3 | import org.banyan.concurrent.base.GenericService; 4 | import org.banyan.concurrent.domain.Message; 5 | import org.junit.Test; 6 | 7 | /** 8 | * @author kris 9 | * @date 2022/10/4 10 | */ 11 | public class GenericServiceTest { 12 | 13 | @Test 14 | public void test1() { 15 | GenericService genericService = new GenericService(); 16 | try { 17 | Message inst = genericService.getObject(Message.class); 18 | inst.setMsg("hello world!!"); 19 | System.out.println(inst.getMsg()); 20 | } catch (InstantiationException e) { 21 | e.printStackTrace(); 22 | } catch (IllegalAccessException e) { 23 | e.printStackTrace(); 24 | } 25 | } 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/HeapOOM.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError 8 | *

9 | * User : krisjin 10 | * Date: 2015/10/14 11 | * Time: 22:37 12 | */ 13 | public class HeapOOM { 14 | public static void main(String[] args) { 15 | List list = new ArrayList(); 16 | 17 | // while (true) { 18 | // list.add(new OOMObject()); 19 | // } 20 | 21 | } 22 | 23 | static class OOMObject { 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/JavaVMStackSOF.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test; 2 | 3 | /** 4 | * 如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛{@link StackOverflowError}异常 5 | * VM Args: -Xss128k 6 | *

7 | * User : krisjin 8 | * Date: 2015/10/14 9 | * Time: 22:56 10 | */ 11 | public class JavaVMStackSOF { 12 | 13 | private int stackLength = 1; 14 | 15 | public void stackLeak() { 16 | stackLength++; 17 | stackLeak(); 18 | } 19 | 20 | public static void main(String[] args) throws Throwable { 21 | JavaVMStackSOF javaVMStackSOF = new JavaVMStackSOF(); 22 | try { 23 | javaVMStackSOF.stackLeak(); 24 | } catch (Throwable e) { 25 | System.out.println("stack length:" + javaVMStackSOF.stackLength); 26 | throw e; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/ListPartition.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test; 2 | 3 | import com.google.common.collect.Lists; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * User:krisjin 10 | * Date:2020-07-22 11 | */ 12 | public class ListPartition { 13 | 14 | public static void main(String[] args) { 15 | List stringList = new ArrayList<>(); 16 | for (int i = 0; i < 10000; i++) { 17 | stringList.add("s" + i); 18 | } 19 | List> listPartition = Lists.partition(stringList, 20); 20 | 21 | for (List l : listPartition) { 22 | l.clear(); 23 | new ArrayList<>(l).clear(); 24 | // listPartition = null; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/ManagementFactoryTest.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test; 2 | 3 | import javax.management.ObjectName; 4 | import java.lang.management.GarbageCollectorMXBean; 5 | import java.lang.management.ManagementFactory; 6 | import java.lang.management.ThreadInfo; 7 | import java.lang.management.ThreadMXBean; 8 | import java.util.List; 9 | 10 | /** 11 | *

12 | * User : krisjin 13 | * Date: 2015/10/14 14 | * Time: 14:20 15 | */ 16 | public class ManagementFactoryTest { 17 | public static void main(String[] args) { 18 | ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); 19 | List garbageCollectorMXBeanList = ManagementFactory.getGarbageCollectorMXBeans(); 20 | 21 | for (GarbageCollectorMXBean gcMXBean : garbageCollectorMXBeanList) { 22 | String gcName = gcMXBean.getName(); 23 | String memoryPoolNames[] = gcMXBean.getMemoryPoolNames(); 24 | for (String memoryPoolName : memoryPoolNames) { 25 | System.out.println(memoryPoolName); 26 | } 27 | ObjectName objectName = gcMXBean.getObjectName(); 28 | String domainName = objectName.getDomain(); 29 | System.out.println(domainName+"__"+objectName.getCanonicalName()); 30 | System.out.println(gcName); 31 | 32 | } 33 | 34 | //不需要获取同步的monitor 和 synchronize信息,仅获取线程和线程堆栈信息。 35 | ThreadInfo[] allThreads = threadMXBean.dumpAllThreads(true, true); 36 | for (ThreadInfo threadInfo : allThreads) { 37 | String threadName = threadInfo.getThreadName(); 38 | long threadId = threadInfo.getThreadId(); 39 | System.out.println(threadName + "," + threadId + "," + threadInfo.getLockOwnerName()); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/MemoryLeakFutureTaskDemo.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test; 2 | 3 | import com.banyan.test.domain.User; 4 | import org.junit.Test; 5 | 6 | import java.util.HashSet; 7 | import java.util.Set; 8 | import java.util.Vector; 9 | 10 | 11 | /** 12 | * 如何判定内存泄露: 13 | * 这些对象是可达的,即在有向图中,存在通路可以与其相连;其次,这些对象是无用的,即程序以后不会再使用这些对象。 14 | * 如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存。 15 | * User: krisjin 16 | * Date: 2016/10/26 17 | */ 18 | public class MemoryLeakFutureTaskDemo { 19 | 20 | /** 21 | * 在循环里申请创建对象,将创建好的对象放到Vector中,然后将对象的引用设置为null,释放引用。 22 | * 如果只是释放引用本身,Vector仍然对该对象有引用,所以垃圾回收并不会回收。 23 | * 简单的释放所有的对象,将Vector对象引用设置null; 24 | * 这样以来存在的对象就处于不可达状态。垃圾回收执行时就会回收这部分内存。 25 | */ 26 | @Test 27 | public void staticCollection() { 28 | Vector vector = new Vector(10); 29 | for (int i = 0; i < 1000000; i++) { 30 | Object object = new Object(); 31 | vector.add(object); 32 | object = null; 33 | } 34 | } 35 | 36 | @Test 37 | public void newInstance() { 38 | for (; ; ) { 39 | Object object = new Object(); 40 | object = null; 41 | } 42 | } 43 | 44 | 45 | /** 46 | * 使用集合时,存储的对象实现了hashcode。对已添加的集合对象属性进行修改,会出现相同的记录 47 | */ 48 | @Test 49 | public void updatePropertyValue() { 50 | Set userSet = new HashSet(); 51 | User user1 = new User("a", "b", "c"); 52 | User user2 = new User("a2", "b2", "c2"); 53 | User user3 = new User("a3", "b3", "c3"); 54 | userSet.add(user1); 55 | userSet.add(user2); 56 | userSet.add(user3); 57 | System.out.println(userSet.size()); 58 | user1.setUsername("ccc"); 59 | userSet.remove(user1); 60 | userSet.add(user1); 61 | System.out.println(userSet.size()); 62 | 63 | 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/NativeOutOfMemoryErrorTest.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test; 2 | 3 | import java.util.concurrent.CountDownLatch; 4 | 5 | /** 6 | * 这个异常问题本质原因是我们创建了太多的线程,而能创建的线程数是有限制的,导致了异常的发生。能创建的线程数的具体计算公式如下: 7 | * (MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads 8 | * MaxProcessMemory 指的是一个进程的最大内存 9 | * JVMMemory JVM内存 10 | * ReservedOsMemory 保留的操作系统内存 11 | * ThreadStackSize 线程栈的大小 12 | *

13 | * User: krisjin 14 | * Date: 2016/10/25 15 | */ 16 | public class NativeOutOfMemoryErrorTest { 17 | public static void main(String[] args) { 18 | for (int i = 0; ; i++) { 19 | System.out.println("i = " + i); 20 | new Thread(new HoldThread()).start(); 21 | } 22 | } 23 | 24 | static class HoldThread extends Thread { 25 | CountDownLatch countDownLatch = new CountDownLatch(1); 26 | public void run() { 27 | try { 28 | countDownLatch.await(); 29 | } catch (InterruptedException e) { 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/ProducerConsumerQueueTest.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test; 2 | 3 | import org.banyan.concurrent.lock.reentrant.ProducerConsumerQueue; 4 | 5 | /** 6 | * User:krisjin 7 | * Date:2019/3/4 8 | *   9 | */ 10 | public class ProducerConsumerQueueTest { 11 | 12 | public static void main(String[] args) { 13 | ProducerConsumerQueue producerConsumerQueue = new ProducerConsumerQueue(); 14 | Thread take = new Thread(new Runnable() { 15 | @Override 16 | public void run() { 17 | try { 18 | for (; ; ) { 19 | 20 | Object s = producerConsumerQueue.take(); 21 | System.out.println(Thread.currentThread().getName() + " consumer " + s); 22 | } 23 | } catch (InterruptedException e) { 24 | e.printStackTrace(); 25 | } 26 | } 27 | }); 28 | 29 | take.start(); 30 | 31 | Thread producer = new Thread(new Runnable() { 32 | @Override 33 | public void run() { 34 | try { 35 | for (int i = 0; i < 1000; i++) { 36 | String str = "result " + i; 37 | producerConsumerQueue.put(str); 38 | System.out.println(Thread.currentThread().getName() + " producer " + i); 39 | } 40 | 41 | } catch (InterruptedException e) { 42 | e.printStackTrace(); 43 | } 44 | } 45 | }); 46 | 47 | producer.start(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/RuntimeConstantPoolOOM.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * Jdk1.6 8 | * VM Args: -XX:PermSize=10m -XX:MaxPermSize=10m 9 | *

10 | * User : krisjin 11 | * Date: 2015/10/14 12 | * Time: 23:09 13 | */ 14 | public class RuntimeConstantPoolOOM { 15 | 16 | public static void main(String[] args) { 17 | //使用List保持着常量池的引用,避免Full GC回收常量池 18 | List list = new ArrayList(); 19 | //10MB的PermSize在integer范围内足够产生OOM了 20 | int i = 0; 21 | while (true) { 22 | list.add(String.valueOf(i++).intern()); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/domain/Address.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test.domain; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | import java.util.List; 6 | 7 | /** 8 | * User krisjin 9 | * Date 2017/7/12 10 | */ 11 | public class Address { 12 | 13 | private Long id; 14 | 15 | public Long getId() { 16 | return id; 17 | } 18 | 19 | public void setId(Long id) { 20 | this.id = id; 21 | } 22 | 23 | public List getDetailList() { 24 | return detailList; 25 | } 26 | 27 | public void setDetailList(List detailList) { 28 | this.detailList = detailList; 29 | } 30 | 31 | private List detailList; 32 | 33 | public static void main(String[] args) { 34 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 35 | 36 | Date d = new Date(); 37 | 38 | d.setTime(1584606703684L); 39 | String a= simpleDateFormat.format(d); 40 | System.err.println(a); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/domain/Detail.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test.domain; 2 | 3 | /** 4 | * User krisjin 5 | * Date 2017/7/12 6 | */ 7 | public class Detail { 8 | private String value; 9 | public String getValue() { 10 | return value; 11 | } 12 | 13 | public void setValue(String value) { 14 | this.value = value; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/domain/Person.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test.domain; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * User krisjin 7 | * Date 2017/7/12 8 | */ 9 | public class Person { 10 | 11 | private Long id; 12 | private List

addressList; 13 | 14 | public Long getId() { 15 | return id; 16 | } 17 | 18 | public void setId(Long id) { 19 | this.id = id; 20 | } 21 | 22 | public List
getAddressList() { 23 | return addressList; 24 | } 25 | 26 | public void setAddressList(List
addressList) { 27 | this.addressList = addressList; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/domain/User.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test.domain; 2 | 3 | /** 4 | * User: krisjin 5 | * Date: 2016/10/27 6 | */ 7 | public class User { 8 | private String username; 9 | private String nickname; 10 | private String email; 11 | 12 | public User(String username, String nickname, String email) { 13 | this.username = username; 14 | this.nickname = nickname; 15 | this.email = email; 16 | } 17 | 18 | 19 | public String getUsername() { 20 | return username; 21 | } 22 | 23 | public void setUsername(String username) { 24 | this.username = username; 25 | } 26 | 27 | public String getNickname() { 28 | return nickname; 29 | } 30 | 31 | public void setNickname(String nickname) { 32 | this.nickname = nickname; 33 | } 34 | 35 | public String getEmail() { 36 | return email; 37 | } 38 | 39 | public void setEmail(String email) { 40 | this.email = email; 41 | } 42 | 43 | public int hashCode() { 44 | return this.getUsername().hashCode() + this.getNickname().hashCode() + this.getEmail().hashCode(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/com/banyan/test/thread/ThreadDemo.java: -------------------------------------------------------------------------------- 1 | package com.banyan.test.thread; 2 | 3 | import java.util.concurrent.LinkedBlockingQueue; 4 | import java.util.concurrent.TimeUnit; 5 | 6 | /** 7 | * User:krisjin 8 | * Date:2019/5/28 9 | *   10 | */ 11 | public class ThreadDemo { 12 | 13 | 14 | public static void main(String[] args) { 15 | 16 | 17 | ExecutorsUtil executorsUtil = new ExecutorsUtil(10, 10, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1000), "test"); 18 | 19 | 20 | executorsUtil.execute(new Runnable() { 21 | @Override 22 | public void run() { 23 | System.err.println("111"); 24 | } 25 | }); 26 | 27 | // executorsUtil. 28 | 29 | 30 | Thread t = new Thread(new TaskThread()); 31 | t.start(); 32 | } 33 | 34 | 35 | public static class TaskThread implements Runnable { 36 | 37 | @Override 38 | public void run() { 39 | 40 | try { 41 | Thread.sleep(20000); 42 | } catch (InterruptedException e) { 43 | e.printStackTrace(); 44 | } 45 | 46 | System.out.println("Task Thread ..."); 47 | 48 | } 49 | } 50 | } 51 | --------------------------------------------------------------------------------