两线程交替打印数字的代码:

    1. package com.codeday24.demo02;
    2. /**
    3. *
    4. * 线程通信的例子,两个线程交替打印1-100。
    5. *
    6. * 涉及到三个方法:
    7. * wait():一旦执行此方法,当前线程进入阻塞状态,并释放同步监视器。
    8. * notify():一旦执行此方法,就会唤醒被wait的一个线程,如果有多个线程被wait,就唤醒优先级高的
    9. * notifyAll():唤醒所有的线程。
    10. *
    11. * 说明:
    12. * 1、wait()\notify()\notifyAll()三个方法必须使用在同步代码块或同步方法中;
    13. * 2、三个方法的调用者必须是同步代码块或同步方法中的同步监视器,否则会报异常;
    14. * 3、三个方法定义在Object类中。
    15. *
    16. * 面试题:sleep()和wait()的异同?
    17. * 1、相同点:一旦执行方法都可以使当前线程进入阻塞状态;
    18. * 2、不同点:1)声明的位置不同
    19. * 2)调用的要求不同,sleep()可以在任何场景下调用。wait()只能在同步代码块或同步方法总调用;
    20. * 3)wait()会释放锁,sleep()不会。
    21. *
    22. */
    23. class Number implements Runnable {
    24. private int number = 1;
    25. @Override
    26. public void run() {
    27. while (true) {
    28. synchronized (this) {
    29. notifyAll();//唤醒线程
    30. if (number <= 100) {
    31. System.out.println(Thread.currentThread().getName() + ":" + number);
    32. number++;
    33. try {
    34. //使得调用wait方法的线程进入阻塞状态,wait会释放锁
    35. wait();
    36. } catch (InterruptedException e) {
    37. e.printStackTrace();
    38. }
    39. } else {
    40. break;
    41. }
    42. }
    43. }
    44. }
    45. }
    46. public class CommunicationTest {
    47. public static void main(String[] args) {
    48. Number number = new Number();
    49. Thread t1 = new Thread(number);
    50. Thread t2 = new Thread(number);
    51. t1.setName("线程1");
    52. t2.setName("线程2");
    53. t1.start();
    54. t2.start();
    55. }
    56. }

    注意通信使用的三种方法的作用以及与sleep的区别。

    生产者、消费者问题:
    同步方法或者同步代码块不一定是在重写的run()方法里面。

    1. package com.codeday24.demo03;
    2. /**
    3. * 线程通信的应用:经典例题:生产者、消费者例题
    4. *
    5. * 生产者(Productor)将产品交给店员(Clerk),而消费者(Customer)从店员处
    6. * 取走产品,店员一次只能持有固定数量的产品(比如:20),如果生产者试图
    7. * 生产更多的产品,店员会叫生产者停一下,如果店中有空位放产品了再通
    8. * 知生产者继续生产;如果店中没有产品了,店员会告诉消费者等一下,如
    9. * 果店中有产品了再通知消费者来取走产品。
    10. *
    11. * 分析:
    12. * 1、是否多线程? Yas,at least two objs.
    13. * 2、是否共享数据? 是,产品
    14. * 3、如何解决线程的安全问题?同步机制,有三种方法。
    15. * 4、是否涉及线程通信?是
    16. *
    17. */
    18. class Clerk {//店员
    19. private int productCount = 0;
    20. public synchronized void produceProduct() {// 生产
    21. if(productCount < 20) {
    22. productCount++;
    23. System.out.println(Thread.currentThread().getName() + "开始生产第" + productCount + "个产品");
    24. notify();
    25. }else{
    26. System.out.println("货物滞销了!");
    27. try {
    28. System.out.println("我不进货了,别你妈生产了!");
    29. wait();
    30. } catch (InterruptedException e) {
    31. e.printStackTrace();
    32. }
    33. }
    34. }
    35. public synchronized void customProduct() {// 消费
    36. if(productCount > 0){
    37. System.out.println("消费者来买东西了");
    38. productCount --;
    39. notify();
    40. }else{
    41. System.out.println("卖光了,滚一边去!");
    42. try {
    43. wait();
    44. System.out.println("好叻,这就滚。");
    45. } catch (InterruptedException e) {
    46. e.printStackTrace();
    47. }
    48. }
    49. }
    50. }
    51. class Producer extends Thread {//生产者
    52. private Clerk clerk;
    53. public Producer(Clerk clerk) {
    54. this.clerk = clerk;
    55. }
    56. @Override
    57. public void run() {
    58. System.out.println(Thread.currentThread().getName() + "要生产了...");
    59. while(true) {
    60. try {
    61. Thread.sleep(10);
    62. } catch (InterruptedException e) {
    63. e.printStackTrace();
    64. }
    65. clerk.produceProduct();
    66. }
    67. }
    68. }
    69. class Customer extends Thread {//消费者
    70. private Clerk clerk;
    71. private static int cusCount = 0;
    72. public Customer(Clerk clerk) {
    73. this.clerk = clerk;
    74. }
    75. @Override
    76. public void run() {
    77. System.out.println(Thread.currentThread().getName() + "开始消费...");
    78. while(true) {
    79. try {
    80. Thread.sleep(10);
    81. } catch (InterruptedException e) {
    82. e.printStackTrace();
    83. }
    84. if (cusCount < 100) {
    85. clerk.customProduct();
    86. cusCount++;
    87. System.out.println(Thread.currentThread().getName() + "一共买了" + cusCount + "个产品");
    88. }
    89. }
    90. }
    91. }
    92. public class ProductTest {
    93. public static void main(String[] args) {
    94. Clerk clerk = new Clerk();
    95. Producer p1 = new Producer(clerk);
    96. p1.setName("生产者1");
    97. Producer p2 = new Producer(clerk);
    98. p1.setName("生产者2");
    99. Customer c1 = new Customer(clerk);
    100. c1.setName("消费者1");
    101. p1.start();
    102. c1.start();
    103. }
    104. }