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 }
效果同上