一、join方法
先来看看join的三个重载方法:
final synchronized void join(long millis, int nanos) throws InterruptedException
final synchronized void join(long millis) throws InterruptedException
final synchronized void join() throws InterruptedException
这三个方法都可以
抛出 InterruptedException 异常,join在内部调用wait()方法进行等待,而synchronized关键字使用的是"对象监视器"原理作为同步,
join的主要作用就是同步,它可以使得线程之间的并行执行变为串行执行
join方法最后调用的还是 join(long millis) join()方法中调用的是join(0),当参数是0的时候表示无限期等待
来看看join(long 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) {
//判断线程是否存活,isAlive native方法
while (isAlive()) {
wait(0); //调用wait方法
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
join与异常
在join()过程中,如果当前线程被中断,则当前线程出现异常。(注意是调用thread.join()的线程被中断才会进入异常,比如a线程调用b.join(),a中断会报异常而b中断不会异常)
public class JoinThread extends Thread {
public static void main(String[] args) throws InterruptedException {
final Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("threadA run");
while (true) {
}
}
}, "threadA");
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("threadB run");
threadA.start();
try {
threadA.join();
} catch (InterruptedException e) {
System.out.println("join error ,threadName - > "+Thread.currentThread().getName()+ e);
}
}
}, "threadB");
threadB.start();
// 向threadB发出中断信号
Thread.sleep(1 * 1000);
threadB.interrupt();
}
}
结果如下:
B发生异常,而A并没有。
二、wait方法
属于Object类中,wait 过程中线程会释放对象锁,只有当其他线程调用 notify 才能唤醒此线程。
wait 使用时必须先获取对象锁,即必须在 synchronized 修饰的代码块中使用,那么相应的 notify 方法同样必须在 synchronized 修饰的代码块中使用,如果没有在synchronized 修饰的代码块中使用时运行时会抛出IllegalMonitorStateException的异常。
wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
为什么wait和notify要加锁?
调用wait方法,首先获取监视器锁,获取成功后,会让线程进入等待状态进入等待队列并释放锁,然后当其他线程调用notify或者notifyAll的时候,会选择从等待队列中选择一个线程而执行完notify后,并不会立马唤醒,原因当前线程仍然持有这把锁,处于等待状态的线程无法获取锁。
三、sleep方法
sleep 方法是属于 Thread 类中的,sleep 过程中线程不会释放锁,只会阻塞线程。
让出cpu给其他线程,但是他的监控状态依然保持着,当指定的时间到了又会自动恢复运行状态,可中断。
sleep 给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会