quartz学习笔记三阅读源码

看过前篇的朋友应该知道,作者给我们推荐了阅读的类org.quartz.core.QuartzSchedulerThread

 

在使用层面,我们跟着教程已经可以满足开发需求,而我们学习源码的目的需求为了提高自己的代码水平,这包括实现原理,设计模式,实践经验等。

 

QuartzSchedulerThread一眼就能看出它是个Thread,我相信一些问题立马就会涌上心头。立刻记下它们,带着问题看才有效果。

 

1. 我对Thread类了解吗?

不是很了解,那先查看一遍Thread类的源码,从上到下阅读下,没用过使用一下.

Thread自身有name,priority,status,控制status的各种方法,用来单独执行某个任务,并且有可控的状态来启停,所以QuartzSchedulerThread也是要独立完成某个任务的。

从QuartzSchedulerThread的注释里可以看出它是用来负责触发触发器Trigger的,run方法里有个while循环不断的检查是否有合适的触发器。

 

2. Thread源码里的name是char[]而不是String,这里System.arraycopy的损耗值得吗?

查阅一番后,这是个遗留问题,据说有些JVM依赖char[] name,有待考证,毕竟很多人说都找不到JVM里调用name的代码。

 

3. 通读完QuartzSchedulerThread,你会发现,这个类自身就是一把锁加一堆状态变量。而ThreadExecutor也只有两个方法initialize和execute,Quartz自身只是实现了execute,只有一行thread.start()。initialize只是用来给我们这种第三方来实现添加一些定制的逻辑。其实这里有两点问题,一个是initialize的必要性,个人感觉可以去掉,二是只是启动一下线程,没必要在写个ThreadExecute,毕竟它也没用到多线程或者线程池,ThreadExecute和锁应该都可以去掉,代码里也没注释为什么这么用,但是加锁了,就说明有并发的需求吧,后期我们魔改的时候可以把锁去掉,看看会出什么幺蛾子,还可以尝试ReentrantLock来替换monitor lock。

 

4. 我们注意到ThreadExecutor是专门放在spi包下的,什么是spi呢?

SPI = Service Provider Interface,可以通过类的全限定名称,定义在配置文件或者别的地方,通过反射来实例化。这个可以学习下,可以方便项目达到可扩展性。

问题:实例化对象的方式有哪些

new Operator

Class.newInstance() 注Class.forName只是用来找Class的,不做实例化,不然Class也不用再写个newInstance()了,对吧。

Constructor newInstance()

Object.clone()

Object Serialization and Deserialization

 

看到这里我们似乎又没有了头绪,就这?

那我们再回头看看作者的推荐引申org.quartz.spi.JobStore.java, org.quartz.spi.ThreadPool.java,org.quartz.core.JobRunShell.java,这里大家可以自行展开,我选择了ThreadPool,因为JobStore是将job写入内存和数据库的两种实现,啃起来一定有点复杂,所以Job相关的先不看,ThreadPool就有点意思了,我们刚看了个Thread却没用ThreadPool,那这个ThreadPool是做什么的呢?

 

正式切入Quartz的ThreadPool,我们第一反应就是java自带了ThreadPoolExecutor,自己干嘛又写了一套,Quartz的ThreadPool有哪些特性是ThreadPoolExecutor所没有的?

 

1. Quartz ThreadPool是什么,如何实现的?

ThreadPool是用来服务QuartzScheduler的,ThreadPool维护了一组线程,已达到复用的目的,将新建的Thread存放在LinkedList里,另外还有两个LinkedList用来放availableThreads和busyThreads,所有的add/remove都只是LinkedList节点的add/remove,无需新建,删除任何Thread。

 

2. Quartz ThreadPool有什么好处和坏处?

好处就是复用,节省资源,节省新建,销毁线程的消耗,可能会挤兑其他进程的资源。

 

3. ThreadPool的实现也有很多,干嘛自己写一套呢,这样设计的目的是什么?Quartz的ThreadPool和常规的Java ThreadPoolExecutor的区别?

首先二者的实现方式区别很大,ThreadPool只是一个fixed pool,ThreadPoolExecutor相对全面。

Quartz是三个LikedList维护Theads,JDK是一个HashSet,一个BlockingQueue。

 

抛开线程组的维护,Quartz的特性应该就是blockForAvailableThreads这个方法了,它是目前没有被使用的线程,但是ThreadPoolExecutor只能获得当前拥有的线程数,而不能获取当前可以使用的。如果要在ThreadPoolExecutor里获得这样的AvailableThreads,首先定义一个fixed pool,比如4,然后prestartAllCoreThreads,然后execute一个线程,然后从workQueue里获取remainingCapacity就是3,就是可以使用的Threads了,这里还必须是ArrayBlockingQueue,LinkedBlockingQueue最大可以是Integer.MAX_VALUE,不符合模拟的条件。

 

Quartz这样做肯定是为了符合自身的业务需求,我们可以尝试使用ThreadPoolExecutor的fixed pool来替换其中的实现,看看能否替换。或者试试自己手动实现。

 

动手是最后的学习模式,下一步就是改造quartz-core。

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值