黑马程序员技术交流社区

标题: 线程间通信练习 [打印本页]

作者: itheima_llt    时间: 2015-4-10 17:50
标题: 线程间通信练习
  1. /*
  2. 这是我写的关于线程间通信的示例。

  3. 线程间的通信:
  4. 其实就是多个线程操作同一个资源,但是操作的动作不同。


  5. 本示例需要定义三个类:
  6. 1 资源类Resource
  7. 2 输入类Input
  8. 3 输出类Output

  9. 步骤:
  10. 1 先写出基本情况
  11. 2 找安全问题并修改
  12. */

  13. /*
  14. //本类定义的资源是,人的数据
  15. class Resource
  16. {
  17.         private String name;//私有化人的名字
  18.         private String sex;//私有化人的性别
  19.        
  20.         //提供set方法,来访问name和sex
  21.         public void set(String name,String sex)
  22.         {
  23.                 this.name = name;
  24.                 this.sex = sex;
  25.         }

  26.         //提供get方法来打印name和sex
  27.         public void get()
  28.         {
  29.                 System.out.println(name+"......"+sex);
  30.         }
  31. }

  32. //本类定义的是往共享数据中存数据
  33. class Input implements Runnable
  34. {
  35.         //私有化共享数据
  36.         private Resource r;

  37.         //利用重载构造函数来传递共享数据
  38.         Input(Resource r)
  39.         {
  40.                 this.r = r;
  41.         }

  42.         //首先覆盖run方法,定义功能:一种情况存入男人,另一种情况存入女人
  43.         public void run()
  44.         {
  45.                 //定义一个布尔变量来区分两种情况
  46.                 boolean flag_in = true;

  47.                 while(true)
  48.                 {
  49.                                 if(flag_in)//如果为真,则存入男,张三
  50.                                 {
  51.                                         r.set("张三","男");
  52.                                         flag_in = false;
  53.                                 }
  54.                                 else//如果为假,则存入女,李丽
  55.                                 {
  56.                                         r.set("李丽",".........女");
  57.                                         flag_in = true;
  58.                                 }
  59.                 }
  60.         }
  61. }

  62. //本类定义的是从共享数据中取数据
  63. class Output implements Runnable
  64. {
  65.         private Resource r;

  66.         Output(Resource r)
  67.         {
  68.                 this.r = r;
  69.         }

  70.         public void run()
  71.         {
  72.                 while(true)
  73.                         r.get();
  74.         }
  75. }



  76. class MyInputOutputDemo
  77. {
  78.         public static void main(String[] args)
  79.         {
  80.                 //建立资源对象
  81.                 Resource r = new Resource();

  82.                 //建立实习了runnable接口的对象
  83.                 Input in = new Input(r);
  84.                 Output out = new Output(r);

  85.                 //建立线程对象
  86.                 Thread t1 = new Thread(in);//输入线程
  87.                 Thread t2 = new Thread(out);//输出线程

  88.                 //启动线程
  89.                 t1.start();
  90.                 t2.start();
  91.         }
  92. }
  93. */
  94. /*
  95. 运行结果中存在:
  96. 李丽......男
  97. 张三...............女
  98. 说明了线程通信存在安全问题
  99. 什么原因呢??
  100. 因为在存数据的同时,还可以取数据。

  101. 下面利用上次所学的解决安全问题的办法
  102. */

  103. /*
  104. //本类定义的资源是,人的数据
  105. class Resource
  106. {
  107.         private String name;//私有化人的名字
  108.         private String sex;//私有化人的性别
  109.         private boolean flag = false;//设置监视器来控制输入输出

  110.         //提供set方法,来访问name和sex
  111.         public void set(String name,String sex)
  112.         {
  113.                 if(!flag)//监视器为假的时候,存入数据
  114.                 {
  115.                         this.name = name;
  116.                         this.sex = sex;
  117.                         flag = true;
  118.                 }
  119.         }

  120.         //提供get方法来打印name和sex
  121.         public void get()
  122.         {
  123.                 if(flag)//监视器为真的时候取出数据
  124.                 {
  125.                         System.out.println(name+"......"+sex);
  126.                         flag = false;
  127.                 }
  128.         }
  129. }

  130. //本类定义的是往共享数据中存数据
  131. class Input implements Runnable
  132. {
  133.         //私有化共享数据
  134.         private Resource r;

  135.         //利用重载构造函数来传递共享数据
  136.         Input(Resource r)
  137.         {
  138.                 this.r = r;
  139.         }

  140.         //首先覆盖run方法,定义功能:一种情况存入男人,另一种情况存入女人
  141.         public void run()
  142.         {
  143.                 //定义一个布尔变量来区分两种情况
  144.                 boolean flag_in = true;

  145.                 while(true)
  146.                 {
  147.                                 if(flag_in)//如果为真,则存入男,张三
  148.                                 {
  149.                                         r.set("张三","男");
  150.                                         flag_in = false;
  151.                                 }
  152.                                 else//如果为假,则存入女,李丽
  153.                                 {
  154.                                         r.set("李丽",".........女");
  155.                                         flag_in = true;
  156.                                 }
  157.                 }
  158.         }
  159. }

  160. //本类定义的是从共享数据中取数据
  161. class Output implements Runnable
  162. {
  163.         private Resource r;

  164.         Output(Resource r)
  165.         {
  166.                 this.r = r;
  167.         }

  168.         public void run()
  169.         {
  170.                 while(true)
  171.                         r.get();
  172.         }
  173. }



  174. class MyInputOutputDemo
  175. {
  176.         public static void main(String[] args)
  177.         {
  178.                 //建立资源对象
  179.                 Resource r = new Resource();

  180.                 //建立实习了runnable接口的对象
  181.                 Input in = new Input(r);
  182.                 Output out = new Output(r);

  183.                 //建立线程对象
  184.                 Thread t1 = new Thread(in);//输入线程
  185.                 Thread t2 = new Thread(out);//输出线程

  186.                 //启动线程
  187.                 t1.start();
  188.                 t2.start();
  189.         }
  190. }
  191. */
  192. /*
  193. 运行结果显示:
  194. 通过给资源增加监视器,已经解决了存取错误的一个问题。

  195. 但是还存在这样的问题:
  196. 张三......男
  197. 张三......男
  198. 张三......男
  199. 李丽...............女

  200. 这说明还存在安全问题。
  201. 这是由于CPU切换造成的。

  202. 正确的情况应该是交替输出:
  203. 存一个取一个。

  204. 那么该怎么解决呢???
  205. Java提供了等待唤醒机制。
  206. 下面改动一下程序。
  207. */

  208. //本类定义的资源是,人的数据
  209. class Resource
  210. {
  211.         private String name;//私有化人的名字
  212.         private String sex;//私有化人的性别
  213.         private boolean flag = false;//设置监视器来控制输入输出

  214.         //提供set方法,来访问name和sex
  215.         public synchronized void set(String name,String sex)
  216.         {
  217.                 if(flag)//监视器为真的时候,等待
  218.                 {
  219.                         try
  220.                         {
  221.                                 this.wait();
  222.                         }
  223.                         catch (Exception e)
  224.                         {
  225.                         }
  226.                 }

  227.                         this.name = name;
  228.                         this.sex = sex;
  229.                         flag = true;
  230.                         this.notify();//唤醒线程池中的第一个线程
  231.         }

  232.         //提供get方法来打印name和sex
  233.         public synchronized void get()
  234.         {
  235.                 if(!flag)//监视器为假的时候,线程等待
  236.                 {
  237.                         try
  238.                         {
  239.                                 this.wait();
  240.                         }
  241.                         catch (Exception e)
  242.                         {
  243.                         }
  244.                 }
  245.                                 System.out.println(name+"......"+sex);
  246.                                 flag = false;
  247.                                 this.notify();//唤醒线程池中的第一个线程
  248.         }
  249. }

  250. //本类定义的是往共享数据中存数据
  251. class Input implements Runnable
  252. {
  253.         //私有化共享数据
  254.         private Resource r;

  255.         //利用重载构造函数来传递共享数据
  256.         Input(Resource r)
  257.         {
  258.                 this.r = r;
  259.         }

  260.         //首先覆盖run方法,定义功能:一种情况存入男人,另一种情况存入女人
  261.         public void run()
  262.         {
  263.                 //定义一个布尔变量来区分两种情况
  264.                 boolean flag_in = true;

  265.                 while(true)
  266.                 {
  267.                                 if(flag_in)//如果为真,则存入男,张三
  268.                                 {
  269.                                         r.set("张三","男");
  270.                                         flag_in = false;
  271.                                 }
  272.                                 else//如果为假,则存入女,李丽
  273.                                 {
  274.                                         r.set("李丽",".........女");
  275.                                         flag_in = true;
  276.                                 }
  277.                 }
  278.         }
  279. }

  280. //本类定义的是从共享数据中取数据
  281. class Output implements Runnable
  282. {
  283.         private Resource r;

  284.         Output(Resource r)
  285.         {
  286.                 this.r = r;
  287.         }

  288.         public void run()
  289.         {
  290.                 while(true)
  291.                         r.get();
  292.         }
  293. }



  294. class MyInputOutputDemo
  295. {
  296.         public static void main(String[] args)
  297.         {
  298.                 //建立资源对象
  299.                 Resource r = new Resource();
  300.                 /*
  301.                 //建立实现了runnable接口的对象
  302.                 Input in = new Input(r);
  303.                 Output out = new Output(r);

  304.                 //建立线程对象
  305.                 Thread t1 = new Thread(in);//输入线程
  306.                 Thread t2 = new Thread(out);//输出线程
  307.                
  308.                 //启动线程
  309.                 t1.start();
  310.                 t2.start();
  311.                 */

  312.                 //上面的6行代码啊可以简化为2行
  313.                 new Thread(new Input(r)).start();
  314.                 new Thread(new Output(r)).start();
  315.                
  316.         }
  317. }
  318. //运行结果显示成功解决输入线程和输出线程通信的安全问题。
复制代码


作者: rick1991chen    时间: 2015-4-22 15:24
顶一个!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2