1.按顺序执行
static class MyThread implements Runnable{
private String name;
public MyThread(String name){
this.name=name;
}
@Override
public void run() {
System.out.println(name + Thread.currentThread());
}
}
public static void main(String[] args) throws InterruptedException {
MyThread AThread = new MyThread("线程A");
MyThread BThread = new MyThread("线程B");
Thread t1 = new Thread(AThread);
Thread t2 = new Thread(BThread);
t1.start();
System.out.println(t1.getName() + t1.isAlive());
System.out.println(t2.getName()+t2.isAlive());
t1.join();
System.out.println(t1.getName() + t1.isAlive());
System.out.println(t2.getName()+t2.isAlive());
t2.start();
System.out.println(t1.getName() + t1.isAlive());
System.out.println(t2.getName()+t2.isAlive());
t2.join();
System.out.println(t1.getName() + t1.isAlive());
System.out.println(t2.getName()+t2.isAlive());
}
2.另一种按顺序执行
static class MyThread implements Runnable{
private String name;
public MyThread(String name){
this.name=name;
}
@Override
public void run() {
System.out.println(name + Thread.currentThread());
}
}
public static void main(String[] args) throws InterruptedException {
MyThread AThread = new MyThread("线程A");
MyThread BThread = new MyThread("线程B");
Thread t1 = new Thread(AThread);
Thread t2 = new Thread(BThread);
t1.start();
t2.start();
System.out.println(t1.getName() + t1.isAlive());
System.out.println(t2.getName()+t2.isAlive());
t1.join();
System.out.println(t1.getName() + t1.isAlive());
System.out.println(t2.getName()+t2.isAlive());
t2.join();
System.out.println(t1.getName() + t1.isAlive());
System.out.println(t2.getName()+t2.isAlive());
}
结论:调用join后,会阻塞当前线程,并且等待子线程执行完唤醒
//join源码
//上的是悲观锁synchronized,因为会进行wait等待操作,是需要持有synchronized锁才能进入等待,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;
}
}
}
//wait
void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
assert(this == JavaThread::current(), "thread consistency check");
...
// Notify waiters on thread object. This has to be done after exit() is called
// on the thread (if the thread is the last thread in a daemon ThreadGroup the
// group should have the destroyed bit set before waiters are notified).
ensure_join(this); //唤醒操作
assert(!this->has_pending_exception(), "ensure_join should have cleared");
...
//ensure_join(this)
static void ensure_join(JavaThread* thread) {
// We do not need to grap the Threads_lock, since we are operating on ourself.
Handle threadObj(thread, thread->threadObj());
assert(threadObj.not_null(), "java thread object must exist");
ObjectLocker lock(threadObj, thread);
// Ignore pending exception (ThreadDeath), since we are exiting anyway
thread->clear_pending_exception();
// Thread is exiting. So set thread_status field in java.lang.Thread class to TERMINATED.
java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED);
// Clear the native thread instance - this makes isAlive return false and allows the join()
// to complete once we've done the notify_all below
//这里是清除native线程,使活跃状态isAlive()方法返回false
java_lang_Thread::set_thread(threadObj(), NULL);
lock.notify_all(thread);//唤醒持有该锁的全部线程
// Ignore pending exception (ThreadDeath), since we are exiting anyway
thread->clear_pending_exception();
}
总结:join方法通过调用线程持有子线程悲观锁synchronized,然后进行wait操作阻塞自己,等待子线程在执行结束后,通过notifyAll操作唤醒持有子线程synchronized锁的所有线程的操作来保证线程的执行顺序,类似于串行化