`

看源码,解疑惑

阅读更多

看JDK源码,解疑惑

 

从SUN公司主页上搞下来JDK5.0的源码,可以好好研究了。开始吧。

 

1、Java定时器原理是怎么样的?

解包jdk_sec-1_5_0-src-jrl,在/j2se/src/share/classes/java/util中找到Timer类。

  1. privateTaskQueuequeue=newTaskQueue();
  2. privateTimerThreadthread=newTimerThread(queue);

我们找到了一个Timer的任务队列,找到了一个实际运行的线程类。

再来看看还有什么:

  1. privatevoidmainLoop(){
  2. while(true){
  3. try{
  4. TimerTasktask;
  5. booleantaskFired;
  6. synchronized(queue){
  7. //Waitforqueuetobecomenon-empty
  8. while(queue.isEmpty()&&newTasksMayBeScheduled)
  9. queue.wait();
  10. if(queue.isEmpty())
  11. break;//Queueisemptyandwillforeverremain;die
  12. //Queuenonempty;lookatfirstevtanddotherightthing
  13. longcurrentTime,executionTime;
  14. task=queue.getMin();
  15. synchronized(task.lock){
  16. if(task.state==TimerTask.CANCELLED){
  17. queue.removeMin();
  18. continue;//Noactionrequired,pollqueueagain
  19. }
  20. currentTime=System.currentTimeMillis();
  21. executionTime=task.nextExecutionTime;
  22. if(taskFired=(executionTime<=currentTime)){
  23. if(task.period==0){//Non-repeating,remove
  24. queue.removeMin();
  25. task.state=TimerTask.EXECUTED;
  26. }else{//Repeatingtask,reschedule
  27. queue.rescheduleMin(
  28. task.period<0?currentTime-task.period
  29. :executionTime+task.period);
  30. }
  31. }
  32. }
  33. if(!taskFired)//Taskhasn'tyetfired;wait
  34. queue.wait(executionTime-currentTime);
  35. }
  36. if(taskFired)//Taskfired;runit,holdingnolocks
  37. task.run();
  38. }catch(InterruptedExceptione){
  39. }
  40. }
  41. }

这是最核心的死循环方法,可以看见,在循环中通过不断地获取系统时间,直到特定时间到达。

-------------------------------------------------------我是无聊的分割线-------------------------------------------------------------------

2、String类型实际是怎么实现的。

  1. /**Thevalueisusedforcharacterstorage.*/
  2. privatefinalcharvalue[];
  3. /**Theoffsetisthefirstindexofthestoragethatisused.*/
  4. privatefinalintoffset;
  5. /**ThecountisthenumberofcharactersintheString.*/
  6. privatefinalintcount;
  7. /**Cachethehashcodeforthestring*/
  8. privateinthash;//Defaultto0

看到了一个char类型数组,它才是实现String的根本,还有几个辅助属性。值得注意的是,String内容实际是不可变的,举例:

  1. publicStringconcat(Stringstr){
  2. intotherLen=str.length();
  3. if(otherLen==0){
  4. returnthis;
  5. }
  6. charbuf[]=newchar[count+otherLen];
  7. getChars(0,count,buf,0);
  8. str.getChars(0,otherLen,buf,count);
  9. returnnewString(0,count+otherLen,buf);
  10. }

这是其中的一个字符串连接的方法,可以看到String所有的方法,只要是牵涉到对字符串更改的,一律调用构造器生成一个新的返回,而根本不更改本身的内容,不过StringBuffer的内容却是可变的,看源码便知。

 

-------------------------------------------------------我是可爱的分割线-------------------------------------------------------------------

 

3、关于Thread。

我们都知道Thread实现了Runnable接口。不过现在我们看看里面的一个有趣的方法:

  1. publicstaticvoidsleep(longmillis,intnanos)
  2. throwsInterruptedException{
  3. if(millis<0){
  4. thrownewIllegalArgumentException("timeoutvalueisnegative");
  5. }
  6. if(nanos<0||nanos>999999){
  7. thrownewIllegalArgumentException(
  8. "nanosecondtimeoutvalueoutofrange");
  9. }
  10. if(nanos>=500000||(nanos!=0&&millis==0)){
  11. millis++;
  12. }
  13. sleep(millis);
  14. }

看到了吧,纳秒——根本就是假的,我们都被JDK骗了。Java常规控制线程的时间精度是非常低的,根本不可能接近纳秒的级别,至于你传入的纳秒参数,下场就是要么变成0,要么变成1毫秒。

 

-------------------------------------------------------我是傻帽的分割线-------------------------------------------------------------------

4、容器类的容量变化的实现:

以Vector为例吧,找到了一个需要变化容量的方法:

  1. //这是它实际存储对象的数组
  2. protectedObject[]elementData;
  3. privatevoidensureCapacityHelper(intminCapacity){
  4. intoldCapacity=elementData.length;
  5. if(minCapacity>oldCapacity){
  6. Object[]oldData=elementData;
  7. intnewCapacity=(capacityIncrement>0)?
  8. (oldCapacity+capacityIncrement):(oldCapacity*2);
  9. if(newCapacity<minCapacity){
  10. newCapacity=minCapacity;
  11. }
  12. elementData=newObject[newCapacity];
  13. System.arraycopy(oldData,0,elementData,0,elementCount);
  14. }
  15. }

可以看到它的容器大小增长策略,如果有合理的增量,当然听用户的,否则简单地乘2完事。

这只是随便挑了几个JDK的类看一看而已,相信进一步的研究会有更多收获。

 

分享到:
评论

相关推荐

    易语言源码winsys.7z

    10. **社区交流**:参与易语言的开发者社区,可以获取最新的技术资讯,交流编程心得,寻求帮助和解答疑惑,进一步提升编程技能。 综上所述,"易语言源码winsys.7z"包含了许多关于易语言编程、Windows系统编程以及...

    C++中const关键字用法详解及实例和源码下载

    最近在学习C++基础部分,看了两天书,已经看过了一遍,半知半解,回过头来重新看第二遍,深入了解一下C++的基础知识。现在读到了const关键字的用法,书上面讲解的时候并没有给出完整的实例,只是理论的讲解了一些...

    JSP基于SSM精品课程学生在线学习平台源码案例设计.zip

    MyBatis是一个轻量级的持久层框架,它简化了SQL操作,将SQL语句与Java代码解耦合。在学生在线学习平台中,MyBatis用于数据库访问,通过XML或注解方式定义SQL语句,实现了数据的增删改查操作。 **5. 学生在线学习...

    awaker,探未来,未解凹谜,阅读.zip

    "Awaker",唤醒者,寓意着这款应用能够唤醒用户的阅读兴趣,提供丰富的文章内容,帮助用户探索未知,解答疑惑。从这个命名中,我们可以感受到开发者对用户体验的关注和对知识传播的热情。 作为一款开源项目,Awaker...

    Iocomp.Net在C#下使用的DEMO

    学习Iocomp.Net的使用,除了参考DEMO代码,还可以查阅官方文档、在线教程以及社区论坛,获取更多实践案例和解答疑惑。 总结,"Iocomp.Net在C#下使用的DEMO"是一个很好的学习资源,它通过具体的实例演示了如何在C#...

    Maven笔记1

    对于依赖的jar包,你可能疑惑应将它们放在何处,是源码库还是项目内?频繁地复制jar包到不同的项目中,这样的做法是否合理?如果你开发的通用组件被多个项目使用,通过邮件分发更新的jar包显然不是一种高效的方法。...

    tidels:Tidels教育网站

    2. **获取源码**:从GitHub或其他版本控制系统克隆或下载Tidels项目的源码,如tidels-master文件。 3. **解压与初始化**:解压缩下载的文件,并在命令行工具中进入项目目录,使用`npm init`命令初始化项目。 4. **...

    《你必须知道的495个C语言问题》

    你难免会遇到各种各样的问题,有些可能让你百思不得其解,甚至翻遍图书馆,也找不到问题的答案。 《你必须知道的495个C语言问题》的出版填补了这一空白。许多知识点的阐述都是其他资料中所没有的,弥足珍贵。 涵盖...

Global site tag (gtag.js) - Google Analytics