public class Demo {
public static void main(String[] agr) throws Exception {
Demo demo = new Demo();
demo.test();
}
//线程的wait,notify必须和synchronized一起使用
//即,当前线程拿属于object的锁之后,就可以调用wait让此线程进入等待状态,然后抛出锁,等待其他线程那到object的锁之后唤醒
//挂在object上的线程,如果有多个线程挂在object一个对象上那么notify只会唤醒一个线程
public Object object = new Object();
public void test() throws InterruptedException {
new Thread() {
@Override
public void run() {
synchronized (object) {
L.d("线程1进入等待状态");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
L.d("线程1继续运行");
}
}
}.start();
new Thread() {
@Override
public void run() {
synchronized (object) {
L.d("线程2进入等待状态");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
L.d("线程2继续运行");
}
}
}.start();
new Thread() {
@Override
public void run() {
synchronized (object) {
L.d("线程3进入等待状态");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
L.d("线程3继续运行");
}
}
}.start();
Thread.sleep(1000);
synchronized (object) {
object.notify();
}
}
}
如果像下面这个没有拿到锁就调起wait就会抛出IllegalMonitorStateException异常
new Thread() {
@Override
public void run() {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
或者是这样,虽然拿到了object的锁但是并没有挂起在object这个对象上就也会抛出异常
new Thread() {
@Override
public void run() {
synchronized (object){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
上面两种直接调用的wait是将自己直接挂在Thread本类这个对象上所以要进行拿到本类对象的锁才可以,像下面这样就不会抛出异常
public void test() throws InterruptedException {
Thread thread = new Thread() {
@Override
public synchronized void run() {
L.d("线程开始");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
L.d("线程完成等待");
}
};
thread.start();
Thread.sleep(1000);
synchronized (thread) {
thread.notify();
}
}
有关线程的状态
NEW | 刚刚创建的线程尚且没有运行 |
RUNNABLE | 正在运行中的线程 |
WAITING | 线程等待中 |
TIMED_WAITING | 计时等待,调用wait(long timeout)之后所处的状态 |
BLOCKED | 阻塞状态,synchronized的锁已经被其他线程拿到而没有释放,此时线程被阻塞在synchronized |
TERMINATED | 终止状态,线程运行完成 |
另外如果线程调用sleep是不会释放已经拿到的synchronized锁,如果是调用wait方法则会释放已经到的synchronized锁
关于thread.join()方法的使用,如果在a线程中调用了b线程的join方法,那么a线程就会进入等待直至b线程执行完成才会继续执行,用网上的专业一点的说法就是将线程由并行转为串行,join内部调用的就是wait方法,
例子:
public void test() {
Thread thread1 = new Thread() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
L.d("线程1 : " + i);
}
}
};
thread1.start();
Thread thread2 = new Thread() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
L.d("线程2 : " + i);
try {
if (i == 5) {
thread1.join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
thread2.start();
}
join方法的源码:
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;
}
}
}