• 传统生产者和消费者问题,Sychronized版和Lock版


    1.生产者和消费者问题Synchronized版

    面试:单例模式、排序算法、生产者消费者、死锁

    1. package com.kuang.pc;
    2. /**
    3. * 线程之间的通信问题,生产者和消费者问题! 等待唤醒 ,通知唤醒
    4. * 线程交替执行 A B 操作同一个变量 num=0
    5. * A num+1;
    6. * B num-1;
    7. */
    8. public class A {
    9. public static void main(String[] args) {
    10. Data data = new Data();
    11. new Thread(()->{
    12. for (int i = 0; i < 10; i++) {
    13. try {
    14. data.increment();
    15. } catch (InterruptedException e) {
    16. e.printStackTrace();
    17. }
    18. }
    19. },"A").start();
    20. new Thread(()->{
    21. for (int i = 0; i < 10; i++) {
    22. try {
    23. data.decrement();
    24. } catch (InterruptedException e) {
    25. e.printStackTrace();
    26. }
    27. }
    28. },"B").start();
    29. }
    30. }
    31. // 判断等待,业务,通知
    32. class Data{//数字 资源类
    33. private int num = 0;
    34. //+1
    35. public synchronized void increment() throws InterruptedException {
    36. if(num!=0){
    37. //等待
    38. this.wait();
    39. }
    40. num++;
    41. //通知其他线程,我+1完毕了
    42. System.out.println(Thread.currentThread().getName()+"=>"+num);
    43. this.notifyAll();
    44. }
    45. //+1
    46. public synchronized void decrement() throws InterruptedException {
    47. if(num==0){
    48. //等待
    49. this.wait();
    50. }
    51. num--;
    52. //通知其他线程,我-1完毕了
    53. System.out.println(Thread.currentThread().getName()+"=>"+num);
    54. this.notifyAll();
    55. }
    56. }

    问题A B C D 开四个线程跑,在if判断之后被唤醒,没判断条件被执行了两次增加,导致的虚假唤醒问题。 

    1. package com.kuang.pc;
    2. /**
    3. * 线程之间的通信问题,生产者和消费者问题! 等待唤醒 ,通知唤醒
    4. * 线程交替执行 A B 操作同一个变量 num=0
    5. * A num+1;
    6. * B num-1;
    7. */
    8. public class A {
    9. public static void main(String[] args) {
    10. Data data = new Data();
    11. new Thread(()->{
    12. for (int i = 0; i < 10; i++) {
    13. try {
    14. data.increment();
    15. } catch (InterruptedException e) {
    16. e.printStackTrace();
    17. }
    18. }
    19. },"A").start();
    20. new Thread(()->{
    21. for (int i = 0; i < 10; i++) {
    22. try {
    23. data.decrement();
    24. } catch (InterruptedException e) {
    25. e.printStackTrace();
    26. }
    27. }
    28. },"B").start();
    29. new Thread(()->{
    30. for (int i = 0; i < 10; i++) {
    31. try {
    32. data.increment();
    33. } catch (InterruptedException e) {
    34. e.printStackTrace();
    35. }
    36. }
    37. },"C").start();
    38. new Thread(()->{
    39. for (int i = 0; i < 10; i++) {
    40. try {
    41. data.decrement();
    42. } catch (InterruptedException e) {
    43. e.printStackTrace();
    44. }
    45. }
    46. },"D").start();
    47. }
    48. }
    49. // 判断等待,业务,通知
    50. class Data{//数字 资源类
    51. private int num = 0;
    52. //+1
    53. public synchronized void increment() throws InterruptedException {
    54. while (num!=0){
    55. //等待
    56. this.wait();
    57. }
    58. num++;
    59. //通知其他线程,我+1完毕了
    60. System.out.println(Thread.currentThread().getName()+"=>"+num);
    61. this.notifyAll();
    62. }
    63. //+1
    64. public synchronized void decrement() throws InterruptedException {
    65. while (num==0){
    66. //等待
    67. this.wait();
    68. }
    69. num--;
    70. //通知其他线程,我-1完毕了
    71. System.out.println(Thread.currentThread().getName()+"=>"+num);
    72. this.notifyAll();
    73. }
    74. }

     

    2.新版Lock锁解决消费者生产者问题。 

     

    1. package com.kuang.pc;
    2. import java.util.concurrent.locks.Condition;
    3. import java.util.concurrent.locks.Lock;
    4. import java.util.concurrent.locks.ReentrantLock;
    5. /**
    6. * 线程之间的通信问题,生产者和消费者问题! 等待唤醒 ,通知唤醒
    7. * 线程交替执行 A B 操作同一个变量 num=0
    8. * A num+1;
    9. * B num-1;
    10. */
    11. public class B {
    12. public static void main(String[] args) {
    13. Data1 data = new Data1();
    14. new Thread(()->{
    15. for (int i = 0; i < 10; i++) {
    16. try {
    17. data.increment();
    18. } catch (InterruptedException e) {
    19. e.printStackTrace();
    20. }
    21. }
    22. },"A").start();
    23. new Thread(()->{
    24. for (int i = 0; i < 10; i++) {
    25. try {
    26. data.decrement();
    27. } catch (InterruptedException e) {
    28. e.printStackTrace();
    29. }
    30. }
    31. },"B").start();
    32. new Thread(()->{
    33. for (int i = 0; i < 10; i++) {
    34. try {
    35. data.increment();
    36. } catch (InterruptedException e) {
    37. e.printStackTrace();
    38. }
    39. }
    40. },"C").start();
    41. new Thread(()->{
    42. for (int i = 0; i < 10; i++) {
    43. try {
    44. data.decrement();
    45. } catch (InterruptedException e) {
    46. e.printStackTrace();
    47. }
    48. }
    49. },"D").start();
    50. }
    51. }
    52. // 判断等待,业务,通知
    53. class Data1 {//数字 资源类
    54. private int num = 0;
    55. Lock lock=new ReentrantLock();
    56. Condition condition = lock.newCondition();
    57. // condition.await();等待
    58. // condition.signalAll();唤醒全部
    59. //+1
    60. public void increment() throws InterruptedException {
    61. lock.lock();
    62. try {
    63. //业务代码
    64. while (num != 0) {
    65. //等待
    66. condition.await();
    67. }
    68. num++;
    69. System.out.println(Thread.currentThread().getName() + "=>" + num);
    70. //通知其他线程,我+1完毕了
    71. condition.signalAll();
    72. } catch (Exception e) {
    73. e.printStackTrace();
    74. } finally {
    75. lock.unlock();
    76. }
    77. }
    78. //+1
    79. public void decrement() throws InterruptedException {
    80. lock.lock();
    81. try {
    82. //业务代码
    83. while (num == 0) {
    84. //等待
    85. condition.await();
    86. }
    87. num--;
    88. System.out.println(Thread.currentThread().getName() + "=>" + num);
    89. //通知其他线程,我-1完毕了
    90. condition.signalAll();
    91. } catch (Exception e) {
    92. e.printStackTrace();
    93. } finally {
    94. lock.unlock();
    95. }
    96. }
    97. }

    任何一个新的技术,绝对不是仅仅只覆盖了原来的技术,优势,和补充!

    Condition 优势精准通知,唤醒线程

    1. package com.kuang.pc;
    2. import java.util.concurrent.locks.Condition;
    3. import java.util.concurrent.locks.Lock;
    4. import java.util.concurrent.locks.ReentrantLock;
    5. /**
    6. * 线程之间的通信问题,生产者和消费者问题! 等待唤醒 ,通知唤醒
    7. * 线程交替执行 A B 操作同一个变量 num=0
    8. * A num+1;
    9. * B num-1;
    10. */
    11. public class C {
    12. public static void main(String[] args) {
    13. Data2 data = new Data2();
    14. new Thread(()->{
    15. for (int i = 0; i < 10; i++) {
    16. data.printA();
    17. }
    18. },"A").start();
    19. new Thread(()->{
    20. for (int i = 0; i < 10; i++) {
    21. data.printB();
    22. }
    23. },"B").start();
    24. new Thread(()->{
    25. for (int i = 0; i < 10; i++) {
    26. data.printC();
    27. }
    28. },"C").start();
    29. }
    30. }
    31. // 判断等待,业务,通知
    32. class Data2 {//数字 资源类
    33. private Lock lock=new ReentrantLock();
    34. private Condition condition1 = lock.newCondition();
    35. private Condition condition2 = lock.newCondition();
    36. private Condition condition3 = lock.newCondition();
    37. private int num=1;
    38. public void printA(){
    39. lock.lock();
    40. try {
    41. if (num!=1){
    42. //等待
    43. condition1.await();
    44. }
    45. num=2;
    46. System.out.println(Thread.currentThread().getName()+":Aaa");
    47. //唤醒,唤醒指定的人,B
    48. condition2.signal();
    49. } catch (Exception e) {
    50. e.printStackTrace();
    51. } finally {
    52. lock.unlock();
    53. }
    54. }
    55. public void printB(){
    56. lock.lock();
    57. try {
    58. if (num!=2){
    59. condition2.await();
    60. }
    61. num=3;
    62. System.out.println(Thread.currentThread().getName()+":Bbb");
    63. condition3.signal();
    64. } catch (Exception e) {
    65. e.printStackTrace();
    66. } finally {
    67. lock.unlock();
    68. }
    69. }
    70. public void printC(){
    71. lock.lock();
    72. try {
    73. if (num!=3){
    74. condition3.await();
    75. }
    76. System.out.println(Thread.currentThread().getName()+":Ccc");
    77. num=1;
    78. condition1.signal();
    79. } catch (Exception e) {
    80. e.printStackTrace();
    81. } finally {
    82. lock.unlock();
    83. }
    84. }
    85. }

    精准唤醒线程  Condition

  • 相关阅读:
    【JVM学习笔记】JVM内存区域定义与内存结构
    Midjourney 商用实战升级版 AI给模特换脸
    矩阵键盘中断扫描
    Betaflight关于STM32F405 SBUS协议兼容硬件电气特性问题
    10 个简单有用的 Python 编程技巧
    k8s nginx .yaml 测试
    C语言之内存函数篇(3)
    pytorch 初始化
    CocosCreator 面试题(五)TS有什么优缺点?为什么要用TS?
    树,二叉树的概念与结构
  • 原文地址:https://blog.csdn.net/qq_53374893/article/details/132916231