皮皮网

【惊鸿源码】【宗祠网站+源码】【收支记录+源码】futuretask 1.8源码

2024-12-25 15:16:35 来源:韩国传奇3源码

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

futuretask 1.8源码

带你学会区分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 在其基础上做了扩展。源码宗祠网站+源码其主要功能是源码在任务提交后,当调用 get 方法时能够阻塞当前业务线程,源码直到任务完成时唤醒。源码

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

       为了确保并发安全,FutureTask 使用 CAS(Compare and Swap)操作来管理 WaitNode 栈。每个新插入的aidl源码解读节点都会使用 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选项的参数传递进去: