忘记在哪看到的,说线程是代码执行的序列,像线一样 代码一句一句执行起来。
最近看java Thread源码,发现些有意思的地方。
1 sleep(long millis, int nanos) 方法,原来nanos不管用,只能精确到毫秒。
public static void sleep(long millis, int nanos) throws InterruptedException { if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } sleep(millis); }
2 run方法是怎么被调用的?
public synchronized void start() { /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */ if (threadStatus != 0 || this != me) throw new IllegalThreadStateException(); group.add(this); start0(); if (stopBeforeStart) { stop0(throwableFromStop); } } private native void start0(); public void run() { if (target != null) { target.run(); } }
这是Thread类的run()方法的代码。一目了然如果target存在的话执行target的run()方法,否则什么也不做。这样我们可以推测(因为Thread 实际运行的方法start0 是native方法 我们看不到它的实现)也就是说Thread的run()方法总是先被调用的,然后调用taget(构造函数中的Runnable对象)的run()方法。
3 join方法,使用wait实现
public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } }
测试代码,用notify唤醒源码里的wait方法
public class JoinDemo { static volatile boolean flag = false; public static void main(String[] args) { final SubClass thread = new SubClass(); thread.setName("subclass"); thread.start(); new Thread() { public void run() { try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (thread) { flag = true; thread.notify(); // 唤醒线程的wait方法,但是isAlive返回true,继续wait } } }.start(); try { thread.join(); // synchronized (thread) { // while (flag == false) // thread.wait(); // // } System.out.println("end"); } catch (InterruptedException e) { System.out.println(" join intertupted"); e.printStackTrace(); } } } class SubClass extends Thread { public void run() { try { Thread.sleep(15000); // 15秒后,线程run方法执行结束,线程DEAD状态,isAlive()返回false } catch (InterruptedException e) { System.out.println("intertupted"); e.printStackTrace(); } System.out.println(" sub class end"); } }
值得注意的地方是,线程对象在wait,但是Thread.run()方法里面的逻辑还在执行,看上去一个线程即在wait又在running~ 很诡异是吧,再测试下,在run方法里调用wait(mills)方法。
public class JoinDemo { static volatile boolean flag = false; public static void main(String[] args) { final SubClass thread = new SubClass(); thread.setName("subclass"); thread.start(); new Thread() { public void run() { try { Thread.sleep(20000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (thread) { flag = true; thread.notifyAll(); } } }.start(); try { thread.join(); // main主线程,调用了thread的监控器的wait // synchronized (thread) { // while (flag == false) // thread.wait(); // // } System.out.println("main end"); } catch (InterruptedException e) { System.out.println(" join intertupted"); e.printStackTrace(); } } } class SubClass extends Thread { int i = 0; public void run() { try { while (i < 5) { synchronized(this){ this.wait(5000L); } System.out.println(i++); } // Thread.sleep(15000); } catch (InterruptedException e) { System.out.println("intertupted"); e.printStackTrace(); } System.out.println(" sub class end"); } }
每个java对象(Object的实例)都有一个等待集(wait set), 调用个对象上执行wait的线程(指令执行运行序列),调用obj.wait()方法,就把自己(线程运行序列,VM内部不是用Thread来表示的吧!!!)加入到等待集,等到notify方法被调用的时候,即obj.notify()或者obj.notifyAll(),notify唤醒等待集中的随机一个wait线程,notifyAll唤醒等待集中的所有线程,被唤醒的线程继续从阻塞的wait方法返回,继续执行代码,判断while里的条件。
* synchronized (obj) { * while (<condition does not hold>) * obj.wait(timeout); * ... // Perform action appropriate to condition * }
为什么java要把wait、notify、notifyAll这些线程间同步的方法设计在根类Object里,而不是放在和Thread相关的类里。可能是因为还是那句话,线程是指令执行的序列,java是纯面向对象语言,指令执行序列上的节点就是面向过程的语言是过程,在面向对象语言中,每个对象的方法构成执行序列,同步可能发生在执行序列的任何地方(对象的方法),所以在Object中实现了同步的方法。另外使用并发包里的Mutex、信号量、Lock这些对象也可实现线程间同步互斥。
4 interrupt、interrupted、isInterrupted区别
public void interrupt() { if (this != Thread.currentThread()) checkAccess(); synchronized (blockerLock) { Interruptible b = blocker; if (b != null) { interrupt0(); // Just to set the interrupt flag b.interrupt(); return; } } interrupt0(); } /** * Tests whether the current thread has been interrupted. The * <i>interrupted status</i> of the thread is cleared by this method. In * other words, if this method were to be called twice in succession, the * second call would return false (unless the current thread were * interrupted again, after the first call had cleared its interrupted * status and before the second call had examined it). * * <p>A thread interruption ignored because a thread was not alive * at the time of the interrupt will be reflected by this method * returning false. * * @return <code>true</code> if the current thread has been interrupted; * <code>false</code> otherwise. * @see #isInterrupted() * @revised 6.0 */ public static boolean interrupted() { return currentThread().isInterrupted(true); } /** * Tests whether this thread has been interrupted. The <i>interrupted * status</i> of the thread is unaffected by this method. * * <p>A thread interruption ignored because a thread was not alive * at the time of the interrupt will be reflected by this method * returning false. * * @return <code>true</code> if this thread has been interrupted; * <code>false</code> otherwise. * @see #interrupted() * @revised 6.0 */ public boolean isInterrupted() { return isInterrupted(false); } /** * Tests if some Thread has been interrupted. The interrupted state * is reset or not based on the value of ClearInterrupted that is * passed. */ private native boolean isInterrupted(boolean ClearInterrupted);
private native void interrupt0();
interrupt0和isInterrupted(boolean ClearInterrupted);都是调用OS本地方法
interrupt():设置中断标志位
isInterrupted() :判断中是否设置断标志位,只读的
interrupt():如果中断标志位设置了,则返回true,并且清空标志位;如果中断标志位没有设置,返回false,中断标志位还是false。
5 涉及到的native方法
/* Some private helper methods */ private native void setPriority0(int newPriority); private native void stop0(Object o); private native void suspend0(); private native void resume0(); private native void interrupt0(); public final native boolean isAlive(); private native boolean isInterrupted(boolean ClearInterrupted); public static native void sleep(long millis) throws InterruptedException; public static native Thread currentThread(); public static native void yield();
6 线程状态
public enum State { /** * Thread state for a thread which has not yet started. */ NEW, /** * Thread state for a runnable thread. A thread in the runnable * state is executing in the Java virtual machine but it may * be waiting for other resources from the operating system * such as processor. */ RUNNABLE, /** * Thread state for a thread blocked waiting for a monitor lock. * A thread in the blocked state is waiting for a monitor lock * to enter a synchronized block/method or * reenter a synchronized block/method after calling * {@link Object#wait() Object.wait}. */ BLOCKED, /** * Thread state for a waiting thread. * A thread is in the waiting state due to calling one of the * following methods: * <ul> * <li>{@link Object#wait() Object.wait} with no timeout</li> * <li>{@link #join() Thread.join} with no timeout</li> * <li>{@link LockSupport#park() LockSupport.park}</li> * </ul> * * <p>A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called <tt>Object.wait()</tt> * on an object is waiting for another thread to call * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on * that object. A thread that has called <tt>Thread.join()</tt> * is waiting for a specified thread to terminate. */ WAITING, /** * Thread state for a waiting thread with a specified waiting time. * A thread is in the timed waiting state due to calling one of * the following methods with a specified positive waiting time: * <ul> * <li>{@link #sleep Thread.sleep}</li> * <li>{@link Object#wait(long) Object.wait} with timeout</li> * <li>{@link #join(long) Thread.join} with timeout</li> * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li> * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li> * </ul> */ TIMED_WAITING, /** * Thread state for a terminated thread. * The thread has completed execution. */ TERMINATED; } /** * Returns the state of this thread. * This method is designed for use in monitoring of the system state, * not for synchronization control. * * @return this thread's state. * @since 1.5 */ public State getState() { // get current thread state return sun.misc.VM.toThreadState(threadStatus); }
7 超时程序的模板式写法。 参考join方法,需要注意的一个地方是纳秒参数不生效。第二个是join(millis)方法不是直接调用sleep(millis)方法的,
public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } }
wait方法的时间依赖于系统定时器的tick的精度,如果wait(millis)方法休眠时间正好等于外层调用的时间,那么皆大欢喜,直接一个调用就完事了;如果wait(millis)休眠时间大于join的millis,那么wait(delay)也直接返回了;只有当wait(millis)休眠时间小于millis的时候,wailt方法会被多次调用。