1.å¸¦ä½ å¦ä¼åºåScheduledThreadPoolExecutorä¸Timer
2.动态代理(2)-CGLIB核心原理和JDK区别
3.ListenableFuture源码解析
4.Java异步任务优化CompletionService
å¸¦ä½ å¦ä¼åºåScheduledThreadPoolExecutorä¸Timer
æè¦ï¼æ¬æç®åä»ç»ä¸ScheduledThreadPoolExecutorç±»ä¸Timerç±»çåºå«ï¼ScheduledThreadPoolExecutorç±»ç¸æ¯äºTimerç±»æ¥è¯´ï¼ç©¶ç«æåªäºä¼å¿ï¼ä»¥åäºè åå«å®ç°ä»»å¡è°åº¦çç®å示ä¾ãJDK1.5å¼å§æä¾ScheduledThreadPoolExecutorç±»ï¼ScheduledThreadPoolExecutor类继æ¿ThreadPoolExecutorç±»éç¨çº¿ç¨æ± å®ç°äºä»»å¡çå¨ææ§è°åº¦åè½ãå¨JDK1.5ä¹åï¼å®ç°ä»»å¡çå¨ææ§è°åº¦ä¸»è¦ä½¿ç¨çæ¯Timerç±»åTimerTaskç±»ãæ¬æï¼å°±ç®åä»ç»ä¸ScheduledThreadPoolExecutorç±»ä¸Timerç±»çåºå«ï¼ScheduledThreadPoolExecutorç±»ç¸æ¯äºTimerç±»æ¥è¯´ï¼ç©¶ç«æåªäºä¼å¿ï¼ä»¥åäºè åå«å®ç°ä»»å¡è°åº¦çç®å示ä¾ã
äºè çåºå«çº¿ç¨è§åº¦Timeræ¯å线ç¨æ¨¡å¼ï¼å¦ææ个TimerTaskä»»å¡çæ§è¡æ¶é´æ¯è¾ä¹ ï¼ä¼å½±åå°å ¶ä»ä»»å¡çè°åº¦æ§è¡ã
ScheduledThreadPoolExecutoræ¯å¤çº¿ç¨æ¨¡å¼ï¼å¹¶ä¸éç¨çº¿ç¨æ± ï¼æ个ScheduledFutureTaskä»»å¡æ§è¡çæ¶é´æ¯è¾ä¹ ï¼ä¸ä¼å½±åå°å ¶ä»ä»»å¡çè°åº¦æ§è¡ã
ç³»ç»æ¶é´ææ度Timerè°åº¦æ¯åºäºæä½ç³»ç»çç»å¯¹æ¶é´çï¼å¯¹æä½ç³»ç»çæ¶é´ææï¼ä¸æ¦æä½ç³»ç»çæ¶é´æ¹åï¼åTimerçè°åº¦ä¸å精确ã
ScheduledThreadPoolExecutorè°åº¦æ¯åºäºç¸å¯¹æ¶é´çï¼ä¸åæä½ç³»ç»æ¶é´æ¹åçå½±åã
æ¯å¦æè·å¼å¸¸Timerä¸ä¼æè·TimerTaskæåºçå¼å¸¸ï¼å ä¸Timeråæ¯å线ç¨çãä¸æ¦æ个è°åº¦ä»»å¡åºç°å¼å¸¸ï¼åæ´ä¸ªçº¿ç¨å°±ä¼ç»æ¢ï¼å ¶ä»éè¦è°åº¦çä»»å¡ä¹ä¸åæ§è¡ã
ScheduledThreadPoolExecutoråºäºçº¿ç¨æ± æ¥å®ç°è°åº¦åè½ï¼æ个任å¡æåºå¼å¸¸åï¼å ¶ä»ä»»å¡ä»è½æ£å¸¸æ§è¡ã
ä»»å¡æ¯å¦å ·å¤ä¼å 级Timerä¸æ§è¡çTimerTaskä»»å¡æ´ä½ä¸æ²¡æä¼å 级çæ¦å¿µï¼åªæ¯æç §ç³»ç»çç»å¯¹æ¶é´æ¥æ§è¡ä»»å¡ã
ScheduledThreadPoolExecutorä¸æ§è¡çScheduledFutureTaskç±»å®ç°äºjava.lang.Comparableæ¥å£åjava.util.concurrent.Delayedæ¥å£ï¼è¿ä¹å°±è¯´æäºScheduledFutureTaskç±»ä¸å®ç°äºä¸¤ä¸ªé常éè¦çæ¹æ³ï¼ä¸ä¸ªæ¯java.lang.Comparableæ¥å£çcompareToæ¹æ³ï¼ä¸ä¸ªæ¯java.util.concurrent.Delayedæ¥å£çgetDelayæ¹æ³ãå¨ScheduledFutureTaskç±»ä¸compareToæ¹æ³å®ç°äºä»»å¡çæ¯è¾ï¼è·ç¦»ä¸æ¬¡æ§è¡çæ¶é´é´éççä»»å¡ä¼æå¨åé¢ï¼ä¹å°±æ¯è¯´ï¼è·ç¦»ä¸æ¬¡æ§è¡çæ¶é´é´éççä»»å¡çä¼å 级æ¯è¾é«ãègetDelayæ¹æ³åè½å¤è¿åè·ç¦»ä¸æ¬¡ä»»å¡æ§è¡çæ¶é´é´éã
æ¯å¦æ¯æ对任å¡æåºTimerä¸æ¯æ对任å¡çæåºã
ScheduledThreadPoolExecutorç±»ä¸å®ä¹äºä¸ä¸ªéæå é¨ç±»DelayedWorkQueueï¼DelayedWorkQueueç±»æ¬è´¨ä¸æ¯ä¸ä¸ªæåºéåï¼ä¸ºéè¦è°åº¦çæ¯ä¸ªä»»å¡æç §è·ç¦»ä¸æ¬¡æ§è¡æ¶é´é´éç大å°æ¥æåº
è½å¦è·åè¿åçç»æTimerä¸æ§è¡çTimerTaskç±»åªæ¯å®ç°äºjava.lang.Runnableæ¥å£ï¼æ æ³ä»TimerTaskä¸è·åè¿åçç»æã
ScheduledThreadPoolExecutorä¸æ§è¡çScheduledFutureTask类继æ¿äºFutureTaskç±»ï¼è½å¤éè¿Futureæ¥è·åè¿åçç»æã
éè¿ä»¥ä¸å¯¹ScheduledThreadPoolExecutorç±»åTimerç±»çåæ对æ¯ï¼ç¸ä¿¡å¨JDK1.5ä¹åï¼å°±æ²¡æ使ç¨Timeræ¥å®ç°å®æ¶ä»»å¡è°åº¦çå¿ è¦äºã
äºè ç®åç示ä¾è¿éï¼ç»åºä½¿ç¨TimeråScheduledThreadPoolExecutorå®ç°å®æ¶è°åº¦çç®å示ä¾ï¼ä¸ºäºç®ä¾¿ï¼æè¿éå°±ç´æ¥ä½¿ç¨å¿åå é¨ç±»çå½¢å¼æ¥æ交任å¡ã
Timerç±»ç®å示ä¾æºä»£ç 示ä¾å¦ä¸æ示ã
packageio.binghe.concurrent.lab;importjava.util.Timer;importjava.util.TimerTask;/***@authorbinghe*@version1.0.0*@descriptionæµè¯Timer*/publicclassTimerTest{ publicstaticvoidmain(String[]args)throwsInterruptedException{ Timertimer=newTimer();timer.scheduleAtFixedRate(newTimerTask(){ @Overridepublicvoidrun(){ System.out.println("æµè¯Timerç±»");}},源码,);Thread.sleep();timer.cancel();}}è¿è¡ç»æå¦ä¸æ示ã
æµè¯Timerç±»æµè¯Timerç±»æµè¯Timerç±»æµè¯Timerç±»æµè¯Timerç±»æµè¯Timerç±»æµè¯Timerç±»æµè¯Timerç±»æµè¯Timerç±»æµè¯Timerç±»ScheduledThreadPoolExecutorç±»ç®å示ä¾æºä»£ç 示ä¾å¦ä¸æ示ã
packageio.binghe.concurrent.lab;importjava.util.concurrent.*;/***@authorbinghe*@version1.0.0*@descriptionæµè¯ScheduledThreadPoolExecutor*/publicclassScheduledThreadPoolExecutorTest{ publicstaticvoidmain(String[]args)throwsInterruptedException{ ScheduledExecutorServicescheduledExecutorService=Executors.newScheduledThreadPool(3);scheduledExecutorService.scheduleAtFixedRate(newRunnable(){ @Overridepublicvoidrun(){ System.out.println("æµè¯æµè¯ScheduledThreadPoolExecutor");}},1,1,TimeUnit.SECONDS);//主线ç¨ä¼ç ç§Thread.sleep();System.out.println("æ£å¨å ³é线ç¨æ± ...");//å ³é线ç¨æ± scheduledExecutorService.shutdown();booleanisClosed;//çå¾ çº¿ç¨æ± ç»æ¢do{ isClosed=scheduledExecutorService.awaitTermination(1,TimeUnit.DAYS);System.out.println("æ£å¨çå¾ çº¿ç¨æ± ä¸çä»»å¡æ§è¡å®æ");}while(!isClosed);System.out.println("ææ线ç¨æ§è¡ç»æï¼çº¿ç¨æ± å ³é");}}è¿è¡ç»æå¦ä¸æ示ã
æµè¯æµè¯ScheduledThreadPoolExecutoræµè¯æµè¯ScheduledThreadPoolExecutoræµè¯æµè¯ScheduledThreadPoolExecutoræµè¯æµè¯ScheduledThreadPoolExecutoræµè¯æµè¯ScheduledThreadPoolExecutoræµè¯æµè¯ScheduledThreadPoolExecutoræµè¯æµè¯ScheduledThreadPoolExecutoræµè¯æµè¯ScheduledThreadPoolExecutoræµè¯æµè¯ScheduledThreadPoolExecutoræ£å¨å ³é线ç¨æ± ...æµè¯æµè¯ScheduledThreadPoolExecutoræ£å¨çå¾ çº¿ç¨æ± ä¸çä»»å¡æ§è¡å®æææ线ç¨æ§è¡ç»æï¼çº¿ç¨æ± å ³é注æï¼å ³äºTimeråScheduledThreadPoolExecutorè¿æå ¶ä»ç使ç¨æ¹æ³ï¼è¿éï¼æå°±ç®åååºä»¥ä¸ä¸¤ä¸ªä½¿ç¨ç¤ºä¾ï¼æ´å¤ç使ç¨æ¹æ³å¤§å®¶å¯ä»¥èªè¡å®ç°ã
æ¬æå享èªå为äºç¤¾åºããé«å¹¶åãScheduledThreadPoolExecutorä¸Timerçåºå«åç®å示ä¾ãï¼ä½è ï¼å°æ²³ã
动态代理(2)-CGLIB核心原理和JDK区别
在先前的文章中,我们探讨了动态代理的大全应用以及JDK动态代理的核心原理。本文将继续探讨CGLIB的源码核心原理及其与JDK动态代理的区别。
JDK动态代理存在一个限制,大全它无法代理那些没有实现接口的源码对象。这是大全旗舰28 源码因为动态代理需要通过实现接口来创建代理类。然而,源码这种限制在实际应用中可能引起一些不便。大全例如,源码当需要代理一个没有接口的大全第三方类,或者根本不希望编写接口时,源码这种限制就变得尤为明显。大全正是源码在这种背景下,CGLIB应运而生。大全
CGLIB通过创建一个继承目标类的源码怎样预览APP源码代理类来实现动态代理。与JDK动态代理不同,CGLIB不通过实现接口来创建代理类,而是通过继承来达到目的。尽管方法的工作逻辑都需要在外部定义,并将其传递给自动生成的代理类,但CGLIB和JDK动态代理在这一方面是相似的。
在代码层面,CGLIB的使用方式与JDK动态代理相似。用户首先提出代理需求,然后Java自动生成代理类。这种模式在CGLIB中同样适用。
CGLIB的核心源码包括创建代理逻辑和生成class对象的方法。在创建代理逻辑时,CGLIB使用缓存机制来提高性能。糖果派对源码搭建当需要创建代理类时,如果缓存中不存在对应的类对象,则会将其包装为一个异步任务FutureTask,并将其放置在缓存中。这种设计可以有效地处理多线程环境下类对象的创建。
CGLIB生成的类包括代理对象类和两个FastClass。FastClass是对代理类和目标类方法的签名hash映射,这使得CGLIB可以直接调用这些方法,避免了反射调用。
总结来说,CGLIB和JDK动态代理在实现方式、性能和适用场景上存在一定的差异。JDK动态代理要求目标类实现接口,而CGLIB可以代理没有接口的forkjoin的join源码类。此外,CGLIB采用继承的方式创建代理类,而JDK动态代理通过实现接口。在性能方面,CGLIB采用FastClass机制,避免了反射调用,从而提高了性能。
ListenableFuture源码解析
ListenableFuture 是 spring 中对 JDK Future 接口的扩展,主要应用于解决在提交线程池的任务拿到 Future 后在 get 方法调用时会阻塞的问题。通过使用 ListenableFuture,可以向其注册回调函数(监听器),当任务完成时,触发回调。Promise 在 Netty 中也实现了类似的秒余额网站源码功能,用于处理类似 Future 的场景。
实现 ListenableFuture 的关键在于 FutureTask 的源码解析。FutureTask 是实现 Future 接口的基础类,ListenableFutureTask 在其基础上做了扩展。其主要功能是在任务提交后,当调用 get 方法时能够阻塞当前业务线程,直到任务完成时唤醒。
FutureTask 通过在内部实现一个轻量级的 Treiber stack 数据结构来管理等待任务完成的线程。这个数据结构由 WaitNode 节点组成,每个节点代表一个等待的线程。当业务线程调用 get 方法时,会将自己插入到 WaitNode 栈中,并且在插入的同时让当前线程进入等待状态。在任务执行完成后,会遍历 WaitNode 栈,唤醒等待的线程。
为了确保并发安全,FutureTask 使用 CAS(Compare and Swap)操作来管理 WaitNode 栈。每个新插入的节点都会使用 CAS 操作与栈顶节点进行比较,并在满足条件时更新栈顶。这一过程保证了插入操作的原子性,防止了并发条件下的数据混乱。同时,插入操作与栈顶节点的更新操作相互交织,确保了数据的一致性和完整性。
在 FutureTask 中,还利用了 LockSupport 类提供的 park 和 unpark 方法来实现线程的等待和唤醒。当线程插入到 WaitNode 栈中后,通过 park 方法将线程阻塞;任务执行完成后,通过 unpark 方法唤醒线程,完成等待与唤醒的流程。
综上所述,ListenableFuture 通过扩展 FutureTask 的功能,实现了任务执行与线程等待的高效管理。通过注册监听器并利用 CAS 操作与 LockSupport 方法,实现了在任务完成时通知回调,解决了异步任务执行时的线程阻塞问题,提高了程序的并发处理能力。
Java异步任务优化CompletionService
在Java异步编程中,CompletionService扮演着优化Future和Callable任务的角色。传统Future设计的缺陷在于通过get方法获取结果时,如果任务未完成则阻塞线程,导致资源占用和效率低下。尤其在处理一批任务时,未完成任务的后续处理需等待所有任务完成,造成资源浪费和不合理的等待时间。
为解决上述问题,CompletionService应运而生。它允许同时提交多个任务,优先处理已完成的任务。通过使用ExecutorCompletionService作为CompletionService的实现类,开发者只需设置线程池并提交任务,CompletionService将自动管理任务的执行和结果的获取。
具体而言,ExecutorCompletionService的关键步骤包括设置线程池、提交任务和通过take方法获取已完成任务的Future。借助其内部类QueueingFuture,任务完成时会自动调用done方法,将任务结果放入阻塞队列中,进而被后续调用take方法的程序获取。
解析源码可见,ExecutorCompletionService的核心逻辑简明扼要。它通过submit方法将任务封装为FutureTask并作为QueueingFuture的属性保存,提交至线程池执行。执行完毕后,run方法调用done方法将FutureTask添加至阻塞队列。最后,take方法从队列中获取已完成的任务。
总结而言,CompletionService通过优化任务执行和结果获取流程,显著提高了异步任务的执行效率和资源利用。作为Java程序员,理解和掌握CompletionService的使用,对于优化代码性能至关重要。