• Java学习-多线程交互


    1-生产者消费者问题

    1. 使用来存放数据
      1.1 把栈改造为支持线程安全
      1.2 把栈的边界操作进行处理,当栈里的数据是0的时候,访问pull的线程就会等待。 当栈里的数据是200的时候,访问push的线程就会等待
    2. 提供一个生产者(Producer)线程类,生产随机大写字符压入到堆栈
    3. 提供一个消费者(Consumer)线程类,从堆栈中弹出字符并打印到控制台
    4. 提供一个测试类,使两个生产者和三个消费者线程同时运行

      1 package multiplethread;
      2 
      3 import java.util.LinkedList;
      4 import java.util.List;
      5 
      6 public class Test_Producer_Consumer {
      7     public static class stack {
      8         List<Character> data = new LinkedList<>();
      9 
     10         public synchronized void push(Character c) {
     11             if (data.size() < 200) {
     12                 data.add(c);
     13                 this.notify();
     14             } else {
     15                 try {
     16                     this.wait();
     17                 } catch (InterruptedException e) {
     18                     // TODO Auto-generated catch block
     19                     e.printStackTrace();
     20                 }
     21             }
     22         }
     23 
     24         public synchronized Character pull() {
     25             if (data.size() > 0) {
     26                 Character c = data.remove(data.size() - 1);
     27                 this.notify();
     28                 return c;
     29             } else {
     30                 try {
     31                     this.wait();
     32                 } catch (InterruptedException e) {
     33                     // TODO Auto-generated catch block
     34                     e.printStackTrace();
     35                 }
     36                 return null;
     37             }
     38 
     39         }
     40 
     41         public synchronized void print() {
     42             System.out.printf("此时栈s的数据是:" + data + "  一共%d个
    ", data.size());
     43         }
     44     }
     45 
     46     public static class Producer extends Thread { // 生产者线程类
     47         String name;
     48         stack s;
     49 
     50         public Producer(stack s, String name) {
     51             this.s = s;
     52             this.name = "Producer " + name;
     53         }
     54 
     55         public void run() {
     56             while (true) {
     57                 Character c = ranChar();
     58                 s.push(c);
     59                 System.out.println(this.name + " 压入:" + c);
     60                 s.print();
     61                 try {
     62                     this.sleep(100);
     63                 } catch (InterruptedException e) {
     64                     // TODO Auto-generated catch block
     65                     e.printStackTrace();
     66                 }
     67             }
     68         }
     69 
     70     }
     71 
     72     public static class Consumer extends Thread { // 消费者线程类
     73         String name;
     74         stack s;
     75 
     76         public Consumer(stack s, String name) {
     77             this.s = s;
     78             this.name = "Consumer " + name;
     79         }
     80 
     81         public void run() {
     82             while (true) {
     83                 Character c = s.pull();
     84                 System.out.println(this.name + " 弹出:" + c);
     85                 s.print();
     86                 try {
     87                     this.sleep(100);
     88                 } catch (InterruptedException e) {
     89                     // TODO Auto-generated catch block
     90                     e.printStackTrace();
     91                 }
     92             }
     93         }
     94     }
     95 
     96     public static class TestThread { // 专门的测试类
     97         public void run() {
     98             stack s = new stack();
     99             for (int i = 0; i < 2; i++) { // 2个生产者
    100                 Producer p = new Producer(s, String.valueOf(i));
    101                 p.start();
    102             }
    103             for (int i = 0; i < 3; i++) { // 3个消费者
    104                 Consumer c = new Consumer(s, String.valueOf(i));
    105                 c.start();
    106             }
    107         }
    108     }
    109 
    110     public static Character ranChar() { // 生成随机的大写字符
    111         int s = (int) 'A';
    112         int e = (int) 'Z';
    113         int n = e - s + 1;
    114         int rnd = (int) (Math.floor(Math.random() * n) + s);
    115         return (char) rnd;
    116     }
    117 
    118     public static void main(String[] args) {
    119         TestThread t = new TestThread();
    120         t.run();
    121 
    122     }
    123 }

    效果图:

     使用Condition对象的生产者-消费者

      1 package multiplethread;
      2 
      3 import java.util.LinkedList;
      4 import java.util.concurrent.locks.Condition;
      5 import java.util.concurrent.locks.Lock;
      6 import java.util.concurrent.locks.ReentrantLock;
      7 
      8 public class Test_Producer_Consumer_Lock_Condition {
      9     public static class stack {
     10         LinkedList<Character> data = new LinkedList<>();
     11         Lock lockData = new ReentrantLock();
     12         Condition conditionOfData = lockData.newCondition();
     13 
     14         public void push(Character c) {
     15             lockData.lock();
     16             if (data.size() < 200) {
     17                 data.add(c);
     18                 // System.out.println( " 压入:" + c);
     19                 // System.out.println("此时栈s的数据是:"+data+" 一共"+data.size()+"个");
     20                 conditionOfData.signalAll();
     21             } else {
     22                 try {
     23                     conditionOfData.await();
     24                 } catch (InterruptedException e) {
     25                     // TODO Auto-generated catch block
     26                     e.printStackTrace();
     27                 }
     28             }
     29             lockData.unlock();
     30         }
     31 
     32         public Character pull() {
     33             lockData.lock();
     34             if (data.size() <= 0) {
     35                 try {
     36                     conditionOfData.await();
     37                 } catch (InterruptedException e) {
     38                     // TODO Auto-generated catch block
     39                     e.printStackTrace();
     40                 }
     41                 lockData.unlock();
     42                 return null;
     43             } else {
     44                 Character c = data.remove(data.size() - 1);
     45                 // System.out.println(" 弹出:" + c);
     46                 // System.out.println("此时栈s的数据是:"+data+" 一共"+data.size()+"个");
     47                 conditionOfData.signalAll();
     48                 lockData.unlock();
     49                 return c;
     50             }
     51         }
     52 
     53         public void print() {
     54             lockData.lock();
     55             System.out.printf("此时栈s的数据是:" + data + "  一共%d个
    ", data.size());
     56             lockData.unlock();
     57         }
     58     }
     59 
     60     public static class Producer extends Thread {
     61         String name;
     62         stack s;
     63 
     64         public Producer(stack s, String name) {
     65             this.s = s;
     66             this.name = "Producer " + name;
     67         }
     68 
     69         public void run() {
     70             while (true) {
     71 
     72                 Character c = ranChar();
     73                 s.push(c);
     74                 System.out.println(this.name + " 压入:" + c);
     75                 // 此时打印极有可能出现重复,不及时
     76                 //直接在Stack类的pull、push方法中打印可以避免,但是无法获取那个线程执行了push、pull
     77                 s.print();
     78 
     79                 try {
     80                     this.sleep(100);
     81                 } catch (InterruptedException e) {
     82                     // TODO Auto-generated catch block
     83                     e.printStackTrace();
     84                 }
     85             }
     86         }
     87     }
     88 
     89     public static class Consumer extends Thread {
     90         String name;
     91         stack s;
     92 
     93         public Consumer(stack s, String name) {
     94             this.s = s;
     95             this.name = "Consumer " + name;
     96         }
     97 
     98         public void run() {
     99             while (true) {
    100 
    101                 Character c = s.pull();
    102                 System.out.println(this.name + " 弹出:" + c);
    103                 // 此时打印极有可能出现重复,不及时
    104                 //直接在Stack类的pull、push方法中打印可以避免,但是无法获取那个线程执行了push、pull
    105                 s.print();
    106 
    107                 try {
    108                     this.sleep(300);
    109                 } catch (InterruptedException e) {
    110                     // TODO Auto-generated catch block
    111                     e.printStackTrace();
    112                 }
    113             }
    114         }
    115     }
    116 
    117     public static class TestThread { // 专门的测试类
    118         public void run() {
    119             stack s = new stack();
    120             for (int i = 0; i < 2; i++) { // 2个生产者
    121                 Producer p = new Producer(s, String.valueOf(i));
    122                 p.start();
    123             }
    124             for (int i = 0; i < 3; i++) { // 3个消费者
    125                 Consumer c = new Consumer(s, String.valueOf(i));
    126                 c.start();
    127             }
    128         }
    129     }
    130 
    131     public static Character ranChar() { // 生成随机的大写字符
    132         int s = (int) 'A';
    133         int e = (int) 'Z';
    134         int n = e - s + 1;
    135         int rnd = (int) (Math.floor(Math.random() * n) + s);
    136         return (char) rnd;
    137     }
    138 
    139     public static void main(String[] args) {
    140         TestThread t = new TestThread();
    141         t.run();
    142 
    143     }
    144 }

    效果同上

  • 相关阅读:
    通过点击切换文本框内容的脚本示例
    使用脚本改变树控件的行为
    javascript动态创建radio button元素支持IE/Firefox
    轻量级的向导控件MultiView
    客户端脚本简单实现Repeater的无刷新分页
    在非web site项目中引用Membership
    逐步认识C#四种判断相等的方法
    C#获取csv文件内容对逗号和引号分隔的处理
    JavaScript之 值类型 和 引用类型 Better
    JS call apply bind 方法的区别 Better
  • 原文地址:https://www.cnblogs.com/gilgamesh-hjb/p/12236390.html
Copyright © 2020-2023  润新知