A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

  1. 线程中的等待唤醒机制
  2. /*
  3. 张三;;;;;;;;;女女女女女女女
  4. 丽丽;;;;;;;;;男
  5. 张三;;;;;;;;;女女女女女女女

  6. class Demo1
  7. {
  8.         String name;
  9.         String sex;
  10. }
  11. class Input implements Runnable
  12. {        private Demo1 d;
  13.         Input(Demo1 d)
  14.                 {
  15.                         this.d=d;
  16.                 }
  17. public void run()
  18.         {        int a=0;
  19.                 while(true)
  20.                 {       
  21.                                 if(a==0)
  22.                                 {
  23.                                         d.name="张三";
  24.                                         d.sex="男";
  25.                                 }
  26.                                 else
  27.                                 {
  28.                                         d.name="丽丽";
  29.                                         d.sex="女女女女女女女";
  30.                                 }
  31.                                 a = (a+1)%2;
  32.                        
  33.                 }
  34.         }
  35. }
  36. class Output implements Runnable
  37. {
  38.         private Demo1 d;
  39.                 Output(Demo1 d)
  40.                         {
  41.                                 this.d=d;
  42.                         }
  43.         public void run()
  44.         {
  45.                 while(true)
  46.                 {       
  47.                                 System.out.println(d.name+";;;;;;;;;"+d.sex);
  48.                        
  49.                 }
  50.         }
  51. }
  52. class Demo
  53. {
  54.         public static void main(String[] args)
  55.         {
  56.                 Demo1 d = new Demo1();
  57.                 Input in =new Input(d);
  58.                 Output out = new Output(d);
  59.                 Thread t = new Thread(in);
  60.                 Thread t1 = new Thread(out);
  61.                 t.start();
  62.                 t1.start();
  63.         }
  64. }*/

  65. //当出现 以上把“丽丽”后面加上男了  男的后面加上女了   情况说明多线程出现了安全问题
  66. //处理方式。加上同步代码块。
  67. /*张三;;;;;;;;;男
  68. 张三;;;;;;;;;男
  69. 张三;;;;;;;;;男
  70. 张三;;;;;;;;;男
  71. 张三;;;;;;;;;男
  72. 张三;;;;;;;;;男
  73. 张三;;;;;;;;;男
  74. 张三;;;;;;;;;男
  75. 张三;;;;;;;;;男
  76. 张三;;;;;;;;;男
  77. 张三;;;;;;;;;男
  78. 张三;;;;;;;;;男
  79. 丽丽;;;;;;;;;女女女女女女女
  80. 丽丽;;;;;;;;;女女女女女女女
  81. 丽丽;;;;;;;;;女女女女女女女
  82. 丽丽;;;;;;;;;女女女女女女女
  83. 丽丽;;;;;;;;;女女女女女女女
  84. 丽丽;;;;;;;;;女女女女女女女
  85. 丽丽;;;;;;;;;女女女女女女女
  86. 丽丽;;;;;;;;;女女女女女女女
  87. 丽丽;;;;;;;;;女女女女女女女
  88. 丽丽;;;;;;;;;女女女女女女女
  89. 丽丽;;;;;;;;;女女女女女女女
  90. class Demo1
  91. {
  92.         String name;
  93.         String sex;
  94. }
  95. class Input implements Runnable
  96. {        private Demo1 d;
  97.         Input(Demo1 d)
  98.                 {
  99.                         this.d=d;
  100.                 }
  101. public void run()
  102.         {        int a=0;
  103.                 while(true)
  104.                 {        synchronized(d) //第一次加上同步代码块,为了解决安全问题
  105.                         {
  106.                                 if(a==0)
  107.                                 {
  108.                                         d.name="张三";
  109.                                         d.sex="男";
  110.                                 }
  111.                                 else
  112.                                 {
  113.                                         d.name="丽丽";
  114.                                         d.sex="女女女女女女女";
  115.                                 }
  116.                                 a = (a+1)%2;
  117.                         }
  118.                 }
  119.         }
  120. }
  121. class Output implements Runnable
  122. {
  123.         private Demo1 d;
  124.                 Output(Demo1 d)
  125.                         {
  126.                                 this.d=d;
  127.                         }
  128.         public void run()
  129.         {
  130.                 while(true)
  131.                 {        synchronized(d)  //第一次加上同步代码块,避免出现错乱 为了解决安全问题
  132.                         {
  133.                                 System.out.println(d.name+";;;;;;;;;"+d.sex);
  134.                         }
  135.                 }
  136.         }
  137. }
  138. class Demo
  139. {
  140.         public static void main(String[] args)
  141.         {
  142.                 Demo1 d = new Demo1();
  143.                 Input in =new Input(d);
  144.                 Output out = new Output(d);
  145.                 Thread t = new Thread(in);
  146.                 Thread t1 = new Thread(out);
  147.                 t.start();
  148.                 t1.start();
  149.         }
  150. }*/
  151. /*
  152.         可是呢这样看上去结果很不好,我想让他在往里面输入值的时候吧,
  153.         输入一次,我打印一次,而不是一次性的输入很多,打印很多

  154. 这样就用到了等待唤醒机制。我在赋值的时候先判断一下,里面有没有值,
  155. 如果里面没有值的话,我就往里面输入.当里面有值的时候做一个转换的动作,
  156. 把原来的标记换成,标识里面有数据,这时候线程池中就有一条输出线程在等待,
  157. 就唤醒(notify()唤醒线程池中的第一个等待线程)输出把里面的值给输出,在他输出
  158. 完成以后,也要把标记转换成,里面没有值的情况,在唤醒在线程池中等待的输入线程
  159. 输入线程一判断没有值,就开始赋值,输入和输出交替唤醒等待(wait())。

  160. 张三;;;;;;;;;男
  161. 丽丽;;;;;;;;;女女女女女女女
  162. 张三;;;;;;;;;男
  163. 丽丽;;;;;;;;;女女女女女女女
  164. 张三;;;;;;;;;男
  165. 丽丽;;;;;;;;;女女女女女女女
  166. 张三;;;;;;;;;男
  167. 丽丽;;;;;;;;;女女女女女女女
  168. 张三;;;;;;;;;男
  169. 丽丽;;;;;;;;;女女女女女女女
  170. 张三;;;;;;;;;男
  171. 丽丽;;;;;;;;;女女女女女女女
  172. 张三;;;;;;;;;男
  173. 丽丽;;;;;;;;;女女女女女女女
  174. 张三;;;;;;;;;男
  175. 丽丽;;;;;;;;;女女女女女女女
  176. 张三;;;;;;;;;男
  177. 丽丽;;;;;;;;;女女女女女女女
  178. 这个时候就是交替打印的,输入一次打印一次。
  179. */
  180. /*class Demo1
  181. {
  182.         String name;
  183.         String sex;
  184.         boolean flag = false;
  185. }
  186. class Input implements Runnable
  187. {        private Demo1 d;
  188.         Input(Demo1 d)
  189.                 {
  190.                         this.d=d;
  191.                 }
  192. public void run()
  193.         {        int a=0;
  194.                 while(true)
  195.                 {        synchronized(d) //第一次加上同步代码块,为了解决安全问题,
  196.                         {        if(d.flag)  //第二次加上判断标记如果有就等待,没有就赋值
  197.                                         try{d.wait();}catch(Exception e){}//等待
  198.                                 if(a==0)
  199.                                 {
  200.                                         d.name="张三";
  201.                                         d.sex="男";
  202.                                 }
  203.                                 else
  204.                                 {
  205.                                         d.name="丽丽";
  206.                                         d.sex="女女女女女女女";
  207.                                 }
  208.                                 a = (a+1)%2;
  209.                                 d.flag=true;//第二次加上改变判断标记。
  210.                                 d.notify();//第二次加上唤醒输出线程。
  211.                         }
  212.                 }
  213.         }
  214. }
  215. class Output implements Runnable
  216. {
  217.         private Demo1 d;
  218.                 Output(Demo1 d)
  219.                         {
  220.                                 this.d=d;
  221.                         }
  222.         public void run()
  223.         {
  224.                 while(true)
  225.                 {        synchronized(d)  //第一次加上同步代码块,避免出现错乱 为了解决安全问题
  226.                         {        if(!d.flag)  //第二次加上判断标记如果有就输出,就等待
  227.                                         try{d.wait();}catch(Exception e){}
  228.                                 System.out.println(d.name+";;;;;;;;;"+d.sex);
  229.                                 d.flag=false;  //第二次加上改变判断标记。
  230.                                 d.notify();    //第二次加上唤醒输出线程。
  231.                         }
  232.                 }
  233.         }
  234. }
  235. class Demo
  236. {
  237.         public static void main(String[] args)
  238.         {
  239.                 Demo1 d = new Demo1();
  240.                 Input in =new Input(d);
  241.                 Output out = new Output(d);
  242.                 Thread t = new Thread(in);
  243.                 Thread t1 = new Thread(out);
  244.                 t.start();
  245.                 t1.start();
  246.         }
  247. }*/
  248. //这个时候就在想如果是在多几条线程,操作输入和输出语句的话会不会有问题呢?
  249. /*
  250. 有问题出现了
  251. 张三;;;;;;;;;男
  252. 丽丽;;;;;;;;;女女女女女女女
  253. 丽丽;;;;;;;;;女女女女女女女
  254. 丽丽;;;;;;;;;女女女女女女女
  255. 输出了一个 ,却打印了三个,这又是怎么回事呢?

  256. 发现这是没有判断标记造成的
  257. 为了能够每次都判断标记,把if改成了while这样每次都要判断

  258. 改完以后结果变成这样了
  259. 张三;;;;;;;;;男
  260. 丽丽;;;;;;;;;女女女女女女女
  261. 张三;;;;;;;;;男
  262. 丽丽;;;;;;;;;女女女女女女女
  263. 张三;;;;;;;;;男
  264. 张三;;;;;;;;;男
  265. 程序挂起了不往下运行了,这又是怎么回事呢?

  266. 经解析发现原来把if该成while以后,线程全部被冻结了,所以才会出现挂起现象

  267. 分析;我们现在用的是notify()唤醒的只是一个线程,而notifyAll()唤醒的是全部线程,
  268. 现在呢我们把所有线程都唤醒看看行不行。
  269. 张三;;;;;;;;;男
  270. 张三;;;;;;;;;男
  271. 丽丽;;;;;;;;;女女女女女女女
  272. 丽丽;;;;;;;;;女女女女女女女
  273. 张三;;;;;;;;;男
  274. 张三;;;;;;;;;男
  275. 丽丽;;;;;;;;;女女女女女女女
  276. 丽丽;;;;;;;;;女女女女女女女
  277. 张三;;;;;;;;;男
  278. 张三;;;;;;;;;男
  279. 丽丽;;;;;;;;;女女女女女女女
  280. 丽丽;;;;;;;;;女女女女女女女
  281. 张三;;;;;;;;;男
  282. 这样时可以的。

  283. */
  284. class Demo1
  285. {
  286.         String name;
  287.         String sex;
  288.         boolean flag = false;
  289. }
  290. class Input implements Runnable
  291. {        private Demo1 d;
  292.         Input(Demo1 d)
  293.                 {
  294.                         this.d=d;
  295.                 }
  296. public void run()
  297.         {        int a=0;
  298.                 while(true)
  299.                 {        synchronized(d) //第一次加上同步代码块,为了解决安全问题,
  300.                         {        while(d.flag)  //第二次加上判断标记如果有就等待,没有就赋值
  301.                                         try{d.wait();}catch(Exception e){}//等待
  302.                                 if(a==0)
  303.                                 {
  304.                                         d.name="张三";
  305.                                         d.sex="男";
  306.                                 }
  307.                                 else
  308.                                 {
  309.                                         d.name="丽丽";
  310.                                         d.sex="女女女女女女女";
  311.                                 }
  312.                                 a = (a+1)%2;
  313.                                 d.flag=true;//第二次加上改变判断标记。
  314.                                 d.notifyAll();//第二次加上唤醒输出线程。
  315.                         }
  316.                 }
  317.         }
  318. }
  319. class Output implements Runnable
  320. {
  321.         private Demo1 d;
  322.                 Output(Demo1 d)
  323.                         {
  324.                                 this.d=d;
  325.                         }
  326.         public void run()
  327.         {
  328.                 while(true)
  329.                 {        synchronized(d)  //第一次加上同步代码块,避免出现错乱 为了解决安全问题
  330.                         {        while(!d.flag)  //第二次加上判断标记如果有就输出,就等待
  331.                                         try{d.wait();}catch(Exception e){}
  332.                                 System.out.println(d.name+";;;;;;;;;"+d.sex);
  333.                                 d.flag=false;  //第二次加上改变判断标记。
  334.                                 d.notifyAll();    //第二次加上唤醒输出线程。
  335.                         }
  336.                 }
  337.         }
  338. }
  339. class Demo
  340. {
  341.         public static void main(String[] args)
  342.         {
  343.                 Demo1 d = new Demo1();
  344.                 Input in =new Input(d);
  345.                 Output out = new Output(d);
  346.                 Thread t1 = new Thread(in);
  347.                 Thread t2 = new Thread(in);
  348.                 Thread t3 = new Thread(out);
  349.                 Thread t4 = new Thread(out);
  350.                
  351.                
  352.                 t1.start();
  353.                 t2.start();
  354.                 t3.start();
  355.                 t4.start();
  356.         }
  357. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
菜小徐 + 1

查看全部评分

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马