同步和异步
1. 需要等待结果
1. join实现(同步)
static int result = 0;private static void test1() throws InterruptedException {log.debug("开始");Thread t1 = new Thread(() -> {log.debug("开始");sleep(1);log.debug("结束");result = 10;}, "t1");t1.start();t1.join();log.debug("结果为:{}", result);}
输出
20:30:40.453 [main] c.TestJoin - 开始20:30:40.541 [Thread-0] c.TestJoin - 开始20:30:41.543 [Thread-0] c.TestJoin - 结束20:30:41.551 [main] c.TestJoin - 结果为:10
评价
2. 不需要等待结果
统筹
案例-烧水 泡茶
解法1:join
Thread t1 = new Thread(() -> {log.debug("洗水壶");sleep(1);log.debug("烧开水");sleep(15);}, "老王");Thread t2 = new Thread(() -> {log.debug("洗茶壶");sleep(1);log.debug("洗茶杯");sleep(2);log.debug("拿茶叶");sleep(1);try {t1.join();} catch (InterruptedException e) {e.printStackTrace();}log.debug("泡茶");}, "小王");t1.start();t2.start();
输出
19:19:37.547 [小王] c.TestMakeTea - 洗茶壶19:19:37.547 [老王] c.TestMakeTea - 洗水壶19:19:38.552 [小王] c.TestMakeTea - 洗茶杯19:19:38.552 [老王] c.TestMakeTea - 烧开水19:19:40.553 [小王] c.TestMakeTea - 拿茶叶19:19:53.553 [小王] c.TestMakeTea - 泡茶
解法1 的 缺陷
- 上面模拟的是小王等老王的水烧开了,小王泡茶,如果反过来要实现老王等小王的茶叶拿来了,老王泡茶呢?代码最好能适应两种情况
上面的两个线程其实是各执行各的,如果要模拟老王把水壶交给小王泡茶,或模拟小王把茶叶交给老王泡茶
呢解法2:wait/notify(没懂)
class S2 {static String kettle = "冷水";static String tea = null;static final Object lock = new Object();static boolean maked = false;public static void makeTea() {new Thread(() -> {log.debug("洗水壶");sleep(1);log.debug("烧开水");sleep(5);synchronized (lock) {kettle = "开水";lock.notifyAll();while (tea == null) {try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}if (!maked) {log.debug("拿({})泡({})", kettle, tea);maked = true;}}}, "老王").start();new Thread(() -> {log.debug("洗茶壶");sleep(1);log.debug("洗茶杯");sleep(2);log.debug("拿茶叶");sleep(1);synchronized (lock) {tea = "花茶";lock.notifyAll();while (kettle.equals("冷水")) {try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}if (!maked) {log.debug("拿({})泡({})", kettle, tea);maked = true;}}}, "小王").start();}}
输出
20:04:48.179 c.S2 [小王] - 洗茶壶20:04:48.179 c.S2 [老王] - 洗水壶20:04:49.185 c.S2 [老王] - 烧开水20:04:49.185 c.S2 [小王] - 洗茶杯20:04:51.185 c.S2 [小王] - 拿茶叶20:04:54.185 c.S2 [老王] - 拿(开水)泡(花茶)
解法2 解决了解法1 的问题,不过老王和小王需要相互等待,不如他们只负责各自的任务,泡茶交给第三人来做
解法3:第三者协调(没懂)
class S3 {static String kettle = "冷水";static String tea = null;static final Object lock = new Object();public static void makeTea() {new Thread(() -> {log.debug("洗水壶");sleep(1);log.debug("烧开水");sleep(5);synchronized (lock) {kettle = "开水";lock.notifyAll();}}, "老王").start();new Thread(() -> {log.debug("洗茶壶");sleep(1);log.debug("洗茶杯");sleep(2);log.debug("拿茶叶");sleep(1);synchronized (lock) {tea = "花茶";lock.notifyAll();}}, "小王").start();new Thread(() -> {synchronized (lock) {while (kettle.equals("冷水") || tea == null) {try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}log.debug("拿({})泡({})", kettle, tea);}}, "王夫人").start();}}
输出:
20:13:18.202 c.S3 [小王] - 洗茶壶20:13:18.202 c.S3 [老王] - 洗水壶20:13:19.206 c.S3 [小王] - 洗茶杯20:13:19.206 c.S3 [老王] - 烧开水20:13:21.206 c.S3 [小王] - 拿茶叶20:13:24.207 c.S3 [王夫人] - 拿(开水)泡(花茶)
