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 }

效果同上

原文地址:https://www.cnblogs.com/gilgamesh-hjb/p/12236390.html