目录
内置锁synchronized
保证原子性+可见性
synchronized可以修饰对象和方法
锁的粒度:
- synchronized代码块: 锁对象
- synchronized非静态方法: 锁当前类对象
- synchronized静态方法: 当前类对象的class
package org.example;
/**
* @Author kk
* @Date 2023-10-09 0:07
*/
public class Sync {
private static final Object obj = new Object();
private static int i = 0;
public static void main(String[] args) {
sync1();
new Sync().sync2();
sync3();
}
// 锁class
private synchronized static void sync3() {
i++;
}
// 锁类对象
private synchronized void sync2() {
i++;
}
// 锁obj
private static void sync1() {
synchronized (obj) {
i++;
}
}
}
volatile
保证可见性, 一个线程修改变量值, 另一个线程立即可见
示例:
1. 不加wolatile时, 不会立即可见, 线程2可能不会退出循环

2. 加wolatile时, 立即可见, 线程2退出循环

public class VolatileDemo {
private static volatile int count = 0;
public static void main(String[] args) {
new Thread(() -> {
for (int i = 0; i < 100000000; i++) {
count++;
}
System.out.println("线程1停止 " + System.currentTimeMillis());
}).start();
new Thread(() -> {
while (count != 100000000) {
}
System.out.println("线程2停止 " + System.currentTimeMillis());
}).start();
}
}
wait和notify
- wait: 线程进入等待, 并释放锁
- notify: 唤醒随机一个线程
- notifyAll: 唤醒所有线程
注: 只能在同步方法或者同步代码块使用这三个方法, 尽量使用notifyAll唤醒
示例:
public class NotifyDemo {
private static final Object obj = new Object();
private int distance = 500;
public static void main(String[] args) {
NotifyDemo demo = new NotifyDemo();
// 更新DB, 快递位置
new Thread(demo::updatePosition).start();
// 给用户发送取件短信
new Thread(demo::sendMessage).start();
// 快递运输
new Thread(demo::transport).start();
}
private void transport() {
while (distance > 0) {
SleepTools.second(1);
synchronized (obj) {
// 每走100km通知一次
distance -= 100;
obj.notifyAll();
System.out.println(Thread.currentThread().getName() +": 快递前进100KM, 发送通知");
}
}
}
private void updatePosition() {
synchronized (obj) {
while (distance > 0) {
try {
obj.wait();
System.out.println(Thread.currentThread().getName() +": 更新DB位置, 快递距离" + distance + "KM");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
private void sendMessage() {
synchronized (obj) {
while (distance > 0) {
try {
obj.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println(Thread.currentThread().getName() +": 给用户发送短信, 提示快递到了");
}
}
}
运行结果:
Thread-2: 快递前进100KM, 发送通知
Thread-0: 更新DB位置, 快递距离400KM
Thread-2: 快递前进100KM, 发送通知
Thread-0: 更新DB位置, 快递距离300KM
Thread-2: 快递前进100KM, 发送通知
Thread-0: 更新DB位置, 快递距离200KM
Thread-2: 快递前进100KM, 发送通知
Thread-0: 更新DB位置, 快递距离100KM
Thread-2: 快递前进100KM, 发送通知
Thread-0: 更新DB位置, 快递距离0KM
Thread-1: 给用户发送短信, 提示快递到了
问题
1. 调用yield() 、sleep()、wait()、notify()等方法对锁有何影响?
yield和sleep对锁无影响;
执行wait后会释放锁进入等待状态, 当wait线程被唤醒后, 会去重新竞争锁;
notify对锁也无影响, 只有notify代码块执行完后才会释放锁
2. 为什么wait和notify方法要在同步块中调用?
如果不在同步代码块, 等待和唤醒两个代码块都是随机执行的, 可能造成先唤醒, 再睡眠, 导致永久睡眠的情况
CompletableFuture用法
// 异步执行无返回值
CompletableFuture.runAsync
// 异步执行有返回值
CompletableFuture.supplyAsync
// 任意一个任务跑完就执行后面运算
CompletableFuture.anyOf(future1, future2).thenAccept
// 所有任务跑完才执行后面运算
CompletableFuture.allOf(future1, future2).thenAccept
本文详细介绍了Java中的内置锁synchronized、volatile关键字的特性,以及wait和notify在多线程协作中的应用。同时,对CompletableFuture的异步执行用法进行了概述,包括runAsync,supplyAsync,anyOf和allOf方法。
1155

被折叠的 条评论
为什么被折叠?



