Appearance
join方法
- join方法可以让主线程等待子线程结束后再继续执行
- join方法可以传入一个timeout参数,表示最多等待timeout秒
- join方法可以在子线程中调用,表示等待主线程结束后再继续执行
- join方法可以在主线程中调用,表示等待其他线程结束后再继续执行
- join方法可以在多个线程中调用,表示等待这些线程全部结束后再继续执行
- join方法的使用示例
java
public class JoinDemo {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("Hello from a sub thread!");
});
thread.start();
thread.join();
System.out.println("Hello from main thread!");
}
}
synchronized
- synchronized关键字可以用来修饰方法,也可以用来修饰代码块
- synchronized关键字修饰方法时,表示整个方法是同步的
- synchronized关键字修饰代码块时,需要传入一个对象作为锁
- synchronized关键字修饰代码块时,表示代码块是同步的
- synchronized关键字修饰代码块时,需要注意锁的范围
- synchronized关键字修饰代码块时,需要注意锁的粒度
java
public class SynchronizedDemo {
private int count = 0;
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
public static void main(String[] args) throws InterruptedException {
SynchronizedDemo counter = new SynchronizedDemo();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("Final count: " + counter.getCount());
}
}
wait/notify
- wait方法可以使当前线程等待,直到其他线程调用notify方法唤醒它
- wait方法必须在synchronized代码块中调用
- wait方法会释放锁
- notify方法可以唤醒一个等待的线程
- notify方法必须在synchronized代码块中调用
- notify方法不会释放锁
- wait和notify的使用示例
- wait被唤醒之后,会从当前行后开始执行,这样可能会引起虚假唤醒问题,所以wait始终应该在循环中使用
java
public class WaitNotifyDemo {
private boolean flag = false;
public synchronized void waitForFlag() throws InterruptedException {
while (!flag) {
wait();
}
System.out.println("Flag is true!");
}
public synchronized void setFlag() {
flag = true;
notify();
}
public static void main(String[] args) throws InterruptedException {
WaitNotifyDemo demo = new WaitNotifyDemo();
Thread thread1 = new Thread(() -> {
try {
demo.waitForFlag();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
Thread thread2 = new Thread(() -> {
demo.setFlag();
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
}
await/signal
- await方法可以使当前线程等待,直到其他线程调用signal方法唤醒它
- await和signal方法必须在Lock对象的synchronized代码块中调用
- await方法会释放锁
- signal方法可以唤醒一个等待的线程
java
public class AwaitSignalDemo {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private boolean flag = false;
public void waitForFlag() throws InterruptedException {
lock.lock();
try {
while (!flag) {
condition.await();
}
System.out.println("Flag is true!");
} finally {
lock.unlock();
}
}
public void setFlag() {
lock.lock();
try {
flag = true;
condition.signal();
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
AwaitSignalDemo demo = new AwaitSignalDemo();
Thread thread1 = new Thread(() -> {
try {
demo.waitForFlag();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
Thread thread2 = new Thread(() -> {
demo.setFlag();
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
}
wait和sleep的区别
- sleep是Thread的方法,wait是Object的方法
- sleep不会释放锁,wait会释放锁
- 都可以被interrupted唤醒