java线程(2016-4-7)
Thread.yield()的调用是对线程调度器(Java线程机制的一部分,可以将CPU从一个线程转移到另一个线程)的一种建议,它在声明:"我已经执行完生命周期中最重要的部分了,此刻正是切换给其它任务执行一段时间的大好时机",这完全是选择性的,也就是说可能不会转移到其它线程。
yield()应该做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会。因此,使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。
结论:yield()从未导致线程转到等待/睡眠/阻塞状态。在大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。
Thread.sleep(毫秒数),用在线程的run()方法中,目的是让执行的线程暂停一段时间,那么此时线程的状态是休眠状态,当指定休眠的时间到期,线程就进入可运行状态,但不是运行状态,因此,sleep()中指定的时间是线程不会运行的最短时间,sleep()方法不保证时间到期之后,线程就立即执行。
线程的优先级,尽管CPU处理现有线程集的顺序是不确定的,但是调度器将倾向于让优先权高的线程先执行,然而这并不意味着优先权较低的线程将得不到执行,优先级较低的线程仅仅是执行频率较低。
join()方法,一个线程可以在其它线程之上掉用join()方法,其效果是等待一段时间直到第二个线程结束才继续执行。
由于线程的本质,所以不能在线程外部捕获从线程中逃逸出的异常,一旦异常逃出任务的run()方法,它就会向外传播到控制台。
所有对象都自动含有一把锁(也称为监视器),当在对象上调用其任意的synchronized方法的时候,此对象都被加锁,这时该对象上的其它synchronized方法只有等到前一个方法调用完毕并释放了锁之后才能被调用。其所有的synchronized方法共享同一个锁。
一个任务可以多次获得对象的锁,如果一个方法在同一个对象上调用了第二个方法,后者又调用了同一个对象上的另一个方法,就会发生这种情况,JVM负责跟踪对象被加锁的次数,如果一个对象被解锁(即锁被完全释放),其计数变为0。在任务第一次给对象加锁的时候,计数变为1,每当这个相同的任务在这个对象上获得锁时,计数都会增加,显然,只有首先获得了锁的任务才能允许继续获得多个锁。每当任务离开一个synchronized方法,计数递减,当计数为0时,锁完全被释放。
针对每一个类,也有一个锁(作为Class对象的一部分),所以synchronized static方法可以在类的范围内防止对static数据的访问。
临界区:有时,只是希望防止多个线程同时访问方法内部的部分代码而不是防止访问整个方法,通过这种方式隔离出来的代码被称为临界区,它也使用synchronized关键字建立,这里synchronized被用来指定某个对象,此对象被用来对花括号内的代码进行同步控制。
在进入临济区代码块之前,必须获得synchronized关键字中对象的锁,如果有其它的线程已经得到这个锁,那么就得等到锁被释放之后,才能进入临界区。
线程的本地存储
线程本地存储是一种自动化机制,可以为使用相同变量的每个不同的线程都创建不同的存储,如果你有5个线程都要使用变量x所表示的对象,那么线程本地存储就会生成5个用于x的不同的存储块。主要是,它们使得你可以将状态与线程关联起来。
Thread类包含interrupt()方法,因此你可以终止被阻塞的任务,这个方法将设置线程的中断状态,如果一个线程已经被阻塞了,或者试图执行一个阻塞操作,那么设置线程的中断状态将会抛出InterruptedException,当抛出该异常或者该任务掉用Thread.interrupt()方法时,中断状态被复位。