忘记在哪看到的,说线程是代码执行的序列,像线一样 代码一句一句执行起来。
最近看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方法会被多次调用。