皮皮网
皮皮网

【投资理财系统源码】【程氏3.1源码】【码农源码之家】feturetask源码分析

来源:微擎抖音霸屏源码 发表时间:2024-12-22 02:30:46

1.带你学会区分ScheduledThreadPoolExecutor与Timer
2.ListenableFuture源码解析
3.如何进行ODEX反编译实例

feturetask源码分析

带你学会区分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的区别和简单示例》,作者:冰河。

ListenableFuture源码解析

       ListenableFuture 是 spring 中对 JDK Future 接口的扩展,主要应用于解决在提交线程池的分析任务拿到 Future 后在 get 方法调用时会阻塞的问题。通过使用 ListenableFuture,源码可以向其注册回调函数(监听器),分析投资理财系统源码当任务完成时,源码触发回调。分析Promise 在 Netty 中也实现了类似的源码功能,用于处理类似 Future 的分析场景。

       实现 ListenableFuture 的源码关键在于 FutureTask 的源码解析。FutureTask 是分析实现 Future 接口的基础类,ListenableFutureTask 在其基础上做了扩展。源码程氏3.1源码其主要功能是分析在任务提交后,当调用 get 方法时能够阻塞当前业务线程,源码直到任务完成时唤醒。分析

       FutureTask 通过在内部实现一个轻量级的源码 Treiber stack 数据结构来管理等待任务完成的线程。这个数据结构由 WaitNode 节点组成,码农源码之家每个节点代表一个等待的线程。当业务线程调用 get 方法时,会将自己插入到 WaitNode 栈中,并且在插入的同时让当前线程进入等待状态。在任务执行完成后,2017磁力搜索源码会遍历 WaitNode 栈,唤醒等待的线程。

       为了确保并发安全,FutureTask 使用 CAS(Compare and Swap)操作来管理 WaitNode 栈。每个新插入的hishop 云商城源码节点都会使用 CAS 操作与栈顶节点进行比较,并在满足条件时更新栈顶。这一过程保证了插入操作的原子性,防止了并发条件下的数据混乱。同时,插入操作与栈顶节点的更新操作相互交织,确保了数据的一致性和完整性。

       在 FutureTask 中,还利用了 LockSupport 类提供的 park 和 unpark 方法来实现线程的等待和唤醒。当线程插入到 WaitNode 栈中后,通过 park 方法将线程阻塞;任务执行完成后,通过 unpark 方法唤醒线程,完成等待与唤醒的流程。

       综上所述,ListenableFuture 通过扩展 FutureTask 的功能,实现了任务执行与线程等待的高效管理。通过注册监听器并利用 CAS 操作与 LockSupport 方法,实现了在任务完成时通知回调,解决了异步任务执行时的线程阻塞问题,提高了程序的并发处理能力。

如何进行ODEX反编译实例

       0x 前言

       ä½¿ç”¨å¼€æºå·¥å…·å‡ºçŽ°é—®é¢˜è€Œä¸”很难在网上查找到解决方案的时候,最好的解决方法就是研究它的源码,因为那样能为我们提供更多的信息。

       0x 搭建smali/baksmali源码调试环境

       é¦–先我们在github上拉取smali/baksmali的源码

       git clone /JesusFreke/smali.git

       å¯ä»¥çœ‹å‡ºè¯¥é¡¹ç›®é‡‡ç”¨äº†grade自动化构建工具来编译源码的,因此我们可以在android studio中导入该项目,如下图所示:

       ç”Ÿæˆçš„baksmali在如下目录下面:

       ä¸Šå›¾ä¸­çš„Program arguments中,-a选项代表api level,可以通过如下属性获得:

       æŠ¥é”™å¦‚下:

       Error occurred while disassembling classLandroid.support.v4.util.TimeUtils; - skipping class

       java.lang.RuntimeException: Invalid methodindex:

       atorg.jf.dexlib2.analysis.InlineMethodResolver$InlineMethodResolver_version.resolveExecuteInline(InlineMethodResolver.java:)

       atorg.jf.dexlib2.analysis.MethodAnalyzer.analyzeExecuteInline(MethodAnalyzer.java:)

       atorg.jf.dexlib2.analysis.MethodAnalyzer.analyzeInstruction(MethodAnalyzer.java:)

       atorg.jf.dexlib2.analysis.MethodAnalyzer.analyze(MethodAnalyzer.java:)

       atorg.jf.dexlib2.analysis.MethodAnalyzer.<init>(MethodAnalyzer.java:)

       atorg.jf.baksmali.Adaptors.MethodDefinition.addAnalyzedInstructionMethodItems(MethodDefinition.java:)

       atorg.jf.baksmali.Adaptors.MethodDefinition.getMethodItems(MethodDefinition.java:)

       atorg.jf.baksmali.Adaptors.MethodDefinition.writeTo(MethodDefinition.java:)

       atorg.jf.baksmali.Adaptors.ClassDefinition.writeDirectMethods(ClassDefinition.java:)

       atorg.jf.baksmali.Adaptors.ClassDefinition.writeTo(ClassDefinition.java:)

       atorg.jf.baksmali.baksmali.disassembleClass(baksmali.java:)

       atorg.jf.baksmali.baksmali.access$(baksmali.java:)

       atorg.jf.baksmali.baksmali$1.call(baksmali.java:)

       atorg.jf.baksmali.baksmali$1.call(baksmali.java:)

       atjava.util.concurrent.FutureTask.run(FutureTask.java:)

       atjava.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:)

       atjava.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:)

       atjava.lang.Thread.run(Thread.java:)

       æˆ‘们直接锁定出错的地方,在上面出错信息标红色的地方,并且在抛出异常处下断点,我们可以判断出错原因是因为反编译smali指令execute-line时传入了一个未知的Dalvik虚拟机的内部java方法索引inlineIndex=:

       ç„¶åŽï¼Œæˆ‘们把inline.txt作为-T选项的参数传递进去:

相关栏目:知识