同步和异步

1. 需要等待结果

这时既可以使用同步处理,也可以使用异步来处理

1. join实现(同步)

  1. static int result = 0;
  2. private static void test1() throws InterruptedException {
  3. log.debug("开始");
  4. Thread t1 = new Thread(() -> {
  5. log.debug("开始");
  6. sleep(1);
  7. log.debug("结束");
  8. result = 10;
  9. }, "t1");
  10. t1.start();
  11. t1.join();
  12. log.debug("结果为:{}", result);
  13. }

输出

  1. 20:30:40.453 [main] c.TestJoin - 开始
  2. 20:30:40.541 [Thread-0] c.TestJoin - 开始
  3. 20:30:41.543 [Thread-0] c.TestJoin - 结束
  4. 20:30:41.551 [main] c.TestJoin - 结果为:10

评价

  • 需要外部共享变量,不符合面向对象封装的思想
  • 必须等待线程结束,不能配合线程池使用

    2. Future实现(同步)

2. 不需要等待结果

统筹

案例-烧水 泡茶

解法1:join

  1. Thread t1 = new Thread(() -> {
  2. log.debug("洗水壶");
  3. sleep(1);
  4. log.debug("烧开水");
  5. sleep(15);
  6. }, "老王");
  7. Thread t2 = new Thread(() -> {
  8. log.debug("洗茶壶");
  9. sleep(1);
  10. log.debug("洗茶杯");
  11. sleep(2);
  12. log.debug("拿茶叶");
  13. sleep(1);
  14. try {
  15. t1.join();
  16. } catch (InterruptedException e) {
  17. e.printStackTrace();
  18. }
  19. log.debug("泡茶");
  20. }, "小王");
  21. t1.start();
  22. t2.start();

输出

  1. 19:19:37.547 [小王] c.TestMakeTea - 洗茶壶
  2. 19:19:37.547 [老王] c.TestMakeTea - 洗水壶
  3. 19:19:38.552 [小王] c.TestMakeTea - 洗茶杯
  4. 19:19:38.552 [老王] c.TestMakeTea - 烧开水
  5. 19:19:40.553 [小王] c.TestMakeTea - 拿茶叶
  6. 19:19:53.553 [小王] c.TestMakeTea - 泡茶

解法1 的 缺陷

  • 上面模拟的是小王等老王的水烧开了,小王泡茶,如果反过来要实现老王等小王的茶叶拿来了,老王泡茶呢?代码最好能适应两种情况
  • 上面的两个线程其实是各执行各的,如果要模拟老王把水壶交给小王泡茶,或模拟小王把茶叶交给老王泡茶

    解法2:wait/notify(没懂)

    1. class S2 {
    2. static String kettle = "冷水";
    3. static String tea = null;
    4. static final Object lock = new Object();
    5. static boolean maked = false;
    6. public static void makeTea() {
    7. new Thread(() -> {
    8. log.debug("洗水壶");
    9. sleep(1);
    10. log.debug("烧开水");
    11. sleep(5);
    12. synchronized (lock) {
    13. kettle = "开水";
    14. lock.notifyAll();
    15. while (tea == null) {
    16. try {
    17. lock.wait();
    18. } catch (InterruptedException e) {
    19. e.printStackTrace();
    20. }
    21. }
    22. if (!maked) {
    23. log.debug("拿({})泡({})", kettle, tea);
    24. maked = true;
    25. }
    26. }
    27. }, "老王").start();
    28. new Thread(() -> {
    29. log.debug("洗茶壶");
    30. sleep(1);
    31. log.debug("洗茶杯");
    32. sleep(2);
    33. log.debug("拿茶叶");
    34. sleep(1);
    35. synchronized (lock) {
    36. tea = "花茶";
    37. lock.notifyAll();
    38. while (kettle.equals("冷水")) {
    39. try {
    40. lock.wait();
    41. } catch (InterruptedException e) {
    42. e.printStackTrace();
    43. }
    44. }
    45. if (!maked) {
    46. log.debug("拿({})泡({})", kettle, tea);
    47. maked = true;
    48. }
    49. }
    50. }, "小王").start();
    51. }
    52. }

    输出

    1. 20:04:48.179 c.S2 [小王] - 洗茶壶
    2. 20:04:48.179 c.S2 [老王] - 洗水壶
    3. 20:04:49.185 c.S2 [老王] - 烧开水
    4. 20:04:49.185 c.S2 [小王] - 洗茶杯
    5. 20:04:51.185 c.S2 [小王] - 拿茶叶
    6. 20:04:54.185 c.S2 [老王] - 拿(开水)泡(花茶)

    解法2 解决了解法1 的问题,不过老王和小王需要相互等待,不如他们只负责各自的任务,泡茶交给第三人来做

    解法3:第三者协调(没懂)

    1. class S3 {
    2. static String kettle = "冷水";
    3. static String tea = null;
    4. static final Object lock = new Object();
    5. public static void makeTea() {
    6. new Thread(() -> {
    7. log.debug("洗水壶");
    8. sleep(1);
    9. log.debug("烧开水");
    10. sleep(5);
    11. synchronized (lock) {
    12. kettle = "开水";
    13. lock.notifyAll();
    14. }
    15. }, "老王").start();
    16. new Thread(() -> {
    17. log.debug("洗茶壶");
    18. sleep(1);
    19. log.debug("洗茶杯");
    20. sleep(2);
    21. log.debug("拿茶叶");
    22. sleep(1);
    23. synchronized (lock) {
    24. tea = "花茶";
    25. lock.notifyAll();
    26. }
    27. }, "小王").start();
    28. new Thread(() -> {
    29. synchronized (lock) {
    30. while (kettle.equals("冷水") || tea == null) {
    31. try {
    32. lock.wait();
    33. } catch (InterruptedException e) {
    34. e.printStackTrace();
    35. }
    36. }
    37. log.debug("拿({})泡({})", kettle, tea);
    38. }
    39. }, "王夫人").start();
    40. }
    41. }

    输出:

    1. 20:13:18.202 c.S3 [小王] - 洗茶壶
    2. 20:13:18.202 c.S3 [老王] - 洗水壶
    3. 20:13:19.206 c.S3 [小王] - 洗茶杯
    4. 20:13:19.206 c.S3 [老王] - 烧开水
    5. 20:13:21.206 c.S3 [小王] - 拿茶叶
    6. 20:13:24.207 c.S3 [王夫人] - 拿(开水)泡(花茶)