码迷,mamicode.com
首页 > 其他好文 > 详细

查漏补缺(长期更新)

时间:2015-11-01 18:05:11      阅读:214      评论:0      收藏:0      [点我收藏+]

标签:

前言

Java的部分有基础、设计模式、IO、NIO、多线程,之后有时间还会把集合这部分补上去,这么多内容里面,难免有一些知识点遗漏,本文主要是讲解这些遗漏的知识点。这些知识点,不是特别大的难点,所以没有必要专门写一篇文章讲解;但是这些知识点,也不是一两句话就说得清楚的,所以放在这里。本文和前面的代码优化、类继承接口实现一样,也是一篇长期更新的文章,只要想到有遗漏的知识点,就会随时更新此文。

 

Thread.sleep(XXX)方法消耗CPU吗?

这个知识点是我之前认识一直有错误的一个知识点,在我以前的认识里面,我一直认为Thread.sleep(1000)的这一秒钟的时间内,线程的休眠是一直占用着CPU的时间片休眠的,查看了资料和仔细思考之后发现不是。Thread.sleep(1000)的意思是:代码执行到这儿,1秒钟之内我休息一下,就不参与CPU竞争了,1秒钟之后我再过来参与CPU竞争。

说到这儿,就要顺便再提sleep和wait的区别了,JDK源码提供给我们的注释是非常严谨的:

 1 /**    
 2  * Causes the currently executing thread to sleep (temporarily cease 
 3  * execution) for the specified number of milliseconds, subject to 
 4  * the precision and accuracy of system timers and schedulers. The thread 
 5  * does not lose ownership of any monitors.
 6  *
 7  * @param      millis   the length of time to sleep in milliseconds.
 8  * @exception  InterruptedException if any thread has interrupted
 9  *             the current thread.  The <i>interrupted status</i> of the
10  *             current thread is cleared when this exception is thrown.
11  * @see        Object#notify()
12  */
13 public static native void sleep(long millis) throws InterruptedException;
 1 /**
 2  * Causes the current thread to wait until another thread invokes the 
 3  * {@link java.lang.Object#notify()} method or the 
 4  * {@link java.lang.Object#notifyAll()} method for this object. 
 5  * In other words, this method behaves exactly as if it simply 
 6  * performs the call <tt>wait(0)</tt>.
 7  * <p>
 8  * The current thread must own this object‘s monitor. The thread 
 9  * releases ownership of this monitor and waits until another thread 
10    ...
11  */
12 public final void wait() throws InterruptedException {
13 wait(0);
14 }

看sleep方法的第4、第5行,"The thread does not lose ownership of any monitors"

看wait方法的第8、第9行,"The thread releases ownership of this monitor"

所以二者的差别就来了,差别就在"monitor"也就是监视器上,sleep和wait方法的执行都会释放CPU资源,但是sleep方法不会释放掉监视器的所有权,而wait方法会释放掉监视器的所有权。所谓监视器,就是假如sleep方法和wait方法处于同步方法/同步方法块中,它们所持有的对象锁

 

Thread.sleep(0)的作用

讲这个问题,要先讲一下两种线程调度的方法,周志明老师的《深入理解Java虚拟机:JVM高级特性与最佳实践》第12章第4节对这块内容有比较清楚的解释。

线程调度指的是系统为线程分配处理器使用权的过程,主要调度方式有两种:协同式线程调度抢占式线程调度

1、协同式线程调度

使用协同式线程调度的多线程系统,线程的执行时间由线程本身来控制,线程把自己的工作执行完了之后,要主动通知系统切换到另外一个线程上。这种调度方式最大的好处就是实现简单,而且由于线程要把自己的事情干完了才会进行线程切换,切换操作对线程自己是可知的,所以没有什么线程同步问题。不过协同式线程调度的坏处也很明显:线程执行时间不受控制。如果一个线程编写有问题,一直不告诉系统进行线程切换,那么程序便会一直阻塞在那儿。所以这种方式非常不稳定,一个线程坚持不让出CPU执行时间就可能会导致整个系统崩溃。

2、抢占式线程调度

抢占式线程调度方式是由系统来分配执行时间的,线程切换不由线程本身来决定。在这种实现线程调度的方式下,线程的执行时间是系统可控的,也不会有一个线程导致整个进程阻塞的问题。

很明显Java采取的是抢占式调度方式。Java的线程是通过映射到系统的原生线程上实现的,在某个线程挂起或者分给它的CPU时间片到了之后,操作系统会根据线程优先级、线程饥饿程度等算出一个总的优先级出来,然后再挑选一个线程,分给它时间片。

讲了这么多,回到我们的主题上,我总结两点:

1、CPU分出来的时间片,可以竞争的线程都是会去竞争获取的

2、调用了Thread.sleep(XXX)方法的线程,意味着在XXX毫秒的时间内,该线程不参与CPU时间片的竞争

那么Thread.sleep(0)是干什么用的呢?它的作用就是:强制操作系统触发一次CPU计算优先级并分配时间片的动作。比如线程A获得了5毫秒的CPU执行时间,如果在执行了2毫秒的时候遇到了Thread.sleep(0)语句,那么后面的3毫秒的时间片就不运行了,操作系统重新计算一次优先级,并分配下一个CPU时间片给哪个线程。

这个小细节对于系统运行是有好处的:

1、避免了某一线程长时间占用CPU资源,我们知道在Java中比如开了两个非守护线程,线程优先级为10的线程A与线程优先级为5的线程B同时执行,这意味着操作系统基本上绝大多数时间都在运行线程A,基本不会把CPU控制权交给线程B

2、避免了系统假死

3、让线程有比较平均的机会获得CPU资源

不过Thread.sleep(0)虽然好,但是不要去滥用它。一个系统CPU占用率高是好事情,这意味着CPU在做事情,没有闲着。但是CPU占用率高还得保证CPU做的事情是应该做的事情,比如CPU占用率高,但是在死循环,有意义吗?这就是代码写得有问题。Thread.sleep(0)也一样,这句语句触发了操作系统计算优先级、分配时间片的动作,势必占用CPU的时间,如果在很多线程里面都滥用这个方法的话,CPU使用率是上去了,但大多数时间做的都是无意义的事情。我认为这个动作的目的更多是为了优化系统,而不是代码必须执行的一部分

 

查漏补缺(长期更新)

标签:

原文地址:http://www.cnblogs.com/xrq730/p/4927626.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!