Timer
- Timer支持延迟任务和周期任务
- Timer是一个线程,因此创建Timer开销还是比较大的
- Timer线程并不捕获异常,当task抛出异常时会导致timer取消
- Timer执行周期定时任务,只会开启一个Thread,所以某个task时间过长,会影响task精确性,甚至丢失task调用。(如果task周期是10ms,某个task执行了40ms,那么这个周期任务40ms执行完,可能连续4个调用,或者丢失4个调用)
创建线程的开销
- 关于时间
创建线程使用是直接向系统申请资源的,这里调用系统函数进行分配资源的话耗时不好说。 - 关于资源
Java线程的线程栈所占用的内存是在Java堆外的,所以是不受java程序控制的,只受系统资源限制,默认一个线程的线程栈大小是1M(当让这个可以通过设置-Xss属性设置,但是要注意栈溢出问题),但是,如果每个用户请求都新建线程的话,1024个用户光线程就占用了1个G的内存,如果系统比较大的话,一下子系统资源就不够用了,最后程序就崩溃了。 - 对操作系统来说
创建一个线程的代价是十分昂贵的, 需要给它分配内存、列入调度,同时在线程切换的时候还要执行内存换页,CPU 的缓存被 清空,切换回来的时候还要重新从内存中读取信息,破坏了数据的局部性。
new Timer(). schedule(TimerTask task, Date time)
Schedules the specified task for execution at the specified time.
If the time is in the past, the task is scheduled for immediate execution.
TimerTask
- TimerTask是实现runnable接口的抽象类
一个TimerTask只能分配给一个Timer,如果一个task分配给Timer a, 再分配给 Timer b会报错:java.lang.IllegalStateException: Task already scheduled or cancelled 因为Timer创建Thread开销比较大,所以尽量少创建Timer,可以给Timer分配更多的task
Timer实现原理
Timer是使用Object wait方法实现的,使用的是java api。
object.wait VS Thread.sleep
- sleep属于Thread静态方法, wait属于object方法。
- sleep()方法导致了程序暂停执行指定的时间,让出cpu给其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
- 在调用sleep()方法的过程中,线程不会释放对象锁。而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备
关于很多app刮奖的一点思考?
为什么很多app送东西,都采用刮奖的形式 ,而不是直接送?
我认为主要原因是增加用户的成本,因为免费的东西,用户并不会太关注,一旦用户投入了成本,都会计算收益,所以会不自觉的看送的是什么,并且形成良性互动。
同时刮奖,能够吸引用户的注意,也过滤一些不在乎优惠的用户。