java线程的顺序执行顺序控制
今天看到一个关于如何让线程顺序执行的博文,感觉很有意思。
当然,例子是人家的
public class JoinTest2 {
public static void main(String[] args) {
final Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t1");
}
});
final Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t2");
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t3");
}
});
t3.start();
t2.start();
t1.start();
}
}
从上面的代码中可以看出,创建了三个线程t1,t2,t3,这组带码的意思是三个线程顺序执行,即t1->t2->t3。而完成整个顺序过程知识简单的使用了一个Tread类(java.lang.Thread)的join方法。在java(J2SE8)的官方的api文档中可以看到
join()方法是等待当前线程执行结束。
在这里我想到了Object类(java.lang.Object)中的wait方法,这就是为什么我要写篇文章:做一个对比。
在api文档中是这样描述的
第一个wait()方法描述的意思是,导致当前的线程处于等待状态,直至别的线程使用notify()或者notifyAll()方法唤醒它。
使用wait和notify时有一个比较坑爹的地方是必须要在同步锁内使用,看notify的api描述
/**
* Wakes up a single thread that is waiting on this object's
* monitor. If any threads are waiting on this object, one of them
* is chosen to be awakened. The choice is arbitrary and occurs at
* the discretion of the implementation. A thread waits on an object's
* monitor by calling one of the {@code wait} methods.
* <p>
* The awakened thread will not be able to proceed until the current
* thread relinquishes the lock on this object. The awakened thread will
* compete in the usual manner with any other threads that might be
* actively competing to synchronize on this object; for example, the
* awakened thread enjoys no reliable privilege or disadvantage in being
* the next thread to lock this object.
* <p>
* This method should only be called by a thread that is the owner
* of this object's monitor. A thread becomes the owner of the
* object's monitor in one of three ways:
* <ul>
* <li>By executing a synchronized instance method of that object.
* <li>By executing the body of a {@code synchronized} statement
* that synchronizes on the object.
* <li>For objects of type {@code Class,} by executing a
* synchronized static method of that class.
* </ul>
* <p>
* Only one thread at a time can own an object's monitor.
*
* @throws IllegalMonitorStateException if the current thread is not
* the owner of this object's monitor.
* @see java.lang.Object#notifyAll()
* @see java.lang.Object#wait()
*/
所以我写了如下的代码,看看notify和wait时如何工作
public class threadT implements Runnable
{
public String name = null;
public threadT(String name)
{
this.name = name;
}
@Override
public void run()
{
synchronized (this) {
System.out.println(name);
notify();
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new threadT("run"));
synchronized (thread) {
System.out.println("step1");
thread.start();
System.out.println("step2");
thread.wait();
System.out.println("step3");
}
}
}
其执行结果如下
step1
step2
run
step3
为什么线程的业务功能看似在调用wait()的时候执行,而不是在调用start()的时候?
其原因在start方法的调用机制,当调用start的时候,虚拟机会开两个线程:一个线程调用start方法,另一个线程执行run函数。如果让线程在调用start之后休息10ns(thread.sleep(10)),那么执行就正常了。
step1
run
step2
step3