看JDK源码,解疑惑
从SUN公司主页上搞下来JDK5.0的源码,可以好好研究了。开始吧。
1、Java定时器原理是怎么样的?
解包jdk_sec-1_5_0-src-jrl,在/j2se/src/share/classes/java/util中找到Timer类。
- privateTaskQueuequeue=newTaskQueue();
-
- privateTimerThreadthread=newTimerThread(queue);
我们找到了一个Timer的任务队列,找到了一个实际运行的线程类。
再来看看还有什么:
- privatevoidmainLoop(){
- while(true){
- try{
- TimerTasktask;
- booleantaskFired;
- synchronized(queue){
- while(queue.isEmpty()&&newTasksMayBeScheduled)
- queue.wait();
- if(queue.isEmpty())
- break;
-
- longcurrentTime,executionTime;
- task=queue.getMin();
- synchronized(task.lock){
- if(task.state==TimerTask.CANCELLED){
- queue.removeMin();
- continue;
- }
- currentTime=System.currentTimeMillis();
- executionTime=task.nextExecutionTime;
- if(taskFired=(executionTime<=currentTime)){
- if(task.period==0){
- queue.removeMin();
- task.state=TimerTask.EXECUTED;
- }else{
- queue.rescheduleMin(
- task.period<0?currentTime-task.period
- :executionTime+task.period);
- }
- }
- }
- if(!taskFired)
- queue.wait(executionTime-currentTime);
- }
- if(taskFired)
- task.run();
- }catch(InterruptedExceptione){
- }
- }
- }
这是最核心的死循环方法,可以看见,在循环中通过不断地获取系统时间,直到特定时间到达。
-------------------------------------------------------我是无聊的分割线-------------------------------------------------------------------
2、String类型实际是怎么实现的。
-
- privatefinalcharvalue[];
-
-
- privatefinalintoffset;
-
-
- privatefinalintcount;
-
-
- privateinthash;
看到了一个char类型数组,它才是实现String的根本,还有几个辅助属性。值得注意的是,String内容实际是不可变的,举例:
- publicStringconcat(Stringstr){
- intotherLen=str.length();
- if(otherLen==0){
- returnthis;
- }
- charbuf[]=newchar[count+otherLen];
- getChars(0,count,buf,0);
- str.getChars(0,otherLen,buf,count);
- returnnewString(0,count+otherLen,buf);
- }
这是其中的一个字符串连接的方法,可以看到String所有的方法,只要是牵涉到对字符串更改的,一律调用构造器生成一个新的返回,而根本不更改本身的内容,不过StringBuffer的内容却是可变的,看源码便知。
-------------------------------------------------------我是可爱的分割线-------------------------------------------------------------------
3、关于Thread。
我们都知道Thread实现了Runnable接口。不过现在我们看看里面的一个有趣的方法:
- publicstaticvoidsleep(longmillis,intnanos)
- throwsInterruptedException{
- if(millis<0){
- thrownewIllegalArgumentException("timeoutvalueisnegative");
- }
-
- if(nanos<0||nanos>999999){
- thrownewIllegalArgumentException(
- "nanosecondtimeoutvalueoutofrange");
- }
-
- if(nanos>=500000||(nanos!=0&&millis==0)){
- millis++;
- }
-
- sleep(millis);
- }
看到了吧,纳秒——根本就是假的,我们都被JDK骗了。Java常规控制线程的时间精度是非常低的,根本不可能接近纳秒的级别,至于你传入的纳秒参数,下场就是要么变成0,要么变成1毫秒。
-------------------------------------------------------我是傻帽的分割线-------------------------------------------------------------------
4、容器类的容量变化的实现:
以Vector为例吧,找到了一个需要变化容量的方法:
- protectedObject[]elementData;
-
- privatevoidensureCapacityHelper(intminCapacity){
- intoldCapacity=elementData.length;
- if(minCapacity>oldCapacity){
- Object[]oldData=elementData;
- intnewCapacity=(capacityIncrement>0)?
- (oldCapacity+capacityIncrement):(oldCapacity*2);
- if(newCapacity<minCapacity){
- newCapacity=minCapacity;
- }
- elementData=newObject[newCapacity];
- System.arraycopy(oldData,0,elementData,0,elementCount);
- }
- }
可以看到它的容器大小增长策略,如果有合理的增量,当然听用户的,否则简单地乘2完事。
这只是随便挑了几个JDK的类看一看而已,相信进一步的研究会有更多收获。