一生产一消费:操作栈
本实例是使生产者向堆栈List对象中放入数据,使消费者从List堆栈中取出数据。List最大容量是1
package Third; import java.util.ArrayList; import java.util.List; public class MyStack { private List list = new ArrayList(); synchronized public void push() { try { if (list.size() == 1) { this.wait(); } list.add("anyString=" + Math.random()); this.notify(); System.out.println("push=" + list.size()); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized public String pop() { String returnValue = ""; try { if (list.size() == 0) { System.out.println("pop操作中的:" + Thread.currentThread().getName() + " 线程呈wait状态"); this.wait(); } returnValue = "" + list.get(0); list.remove(0); this.notify(); System.out.println("pop=" + list.size()); } catch (InterruptedException e) { e.printStackTrace(); } return returnValue; } }
package Third; public class P_Thread extends Thread { private P p; public P_Thread(P p) { super(); this.p = p; } @Override public void run() { while (true) { p.pushService(); } } }
package Third; public class C_Thread extends Thread { private C r; public C_Thread(C r) { super(); this.r = r; } @Override public void run() { while (true) { r.popService(); } } }
package Third; public class P { private MyStack myStack; public P(MyStack myStack) { super(); this.myStack = myStack; } public void pushService() { myStack.push(); } }
package Third; public class C { private MyStack myStack; public C(MyStack myStack) { super(); this.myStack = myStack; } public void popService() { System.out.println("pop=" + myStack.pop()); } }
package Third; public class Run { public static void main(String[] args) { MyStack myStack = new MyStack(); P p = new P(myStack); C r = new C(myStack); P_Thread pThread = new P_Thread(p); C_Thread rThread = new C_Thread(r); pThread.start(); rThread.start(); } }
程序运行的结果是size()不会大于1
一生产多消费-操作栈:解决wait条件改变与假死
上述代码只需要更改run.java
package Third; public class Run { public static void main(String[] args) throws InterruptedException { MyStack myStack = new MyStack(); P p = new P(myStack); C r1 = new C(myStack); C r2 = new C(myStack); C r3 = new C(myStack); C r4 = new C(myStack); C r5 = new C(myStack); P_Thread pThread = new P_Thread(p); pThread.start(); C_Thread cThread1 = new C_Thread(r1); C_Thread cThread2 = new C_Thread(r2); C_Thread cThread3 = new C_Thread(r3); C_Thread cThread4 = new C_Thread(r4); C_Thread cThread5 = new C_Thread(r5); cThread1.start(); cThread2.start(); cThread3.start(); cThread4.start(); cThread5.start(); } }
问题的出现是因为在Mystack.java类中使用了if语句作为条件判断。因为条件发生改变时并没有及时的相应,所以多个呈wait状态的线程被唤醒,继而执行list.remove(0)代码而出现异常。解决这个办法是,将if改成while
package Third; import java.util.ArrayList; import java.util.List; public class MyStack { private List list = new ArrayList(); synchronized public void push() { try { while (list.size() == 1) { this.wait(); } list.add("anyString=" + Math.random()); this.notify(); System.out.println("push=" + list.size()); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized public String pop() { String returnValue = ""; try { while (list.size() == 0) { System.out.println("pop操作中的:" + Thread.currentThread().getName() + " 线程呈wait状态"); this.wait(); } returnValue = "" + list.get(0); list.remove(0); this.notify(); System.out.println("pop=" + list.size()); } catch (InterruptedException e) { e.printStackTrace(); } return returnValue; } }
出现了假死状态,解决办法是notifyAll()
多生产与一消费:操作栈
package Third; public class Run { public static void main(String[] args) throws InterruptedException { MyStack myStack = new MyStack(); P p1 = new P(myStack); P p2 = new P(myStack); P p3 = new P(myStack); P p4 = new P(myStack); P p5 = new P(myStack); P p6 = new P(myStack); P_Thread pThread1 = new P_Thread(p1); P_Thread pThread2 = new P_Thread(p2); P_Thread pThread3 = new P_Thread(p3); P_Thread pThread4 = new P_Thread(p4); P_Thread pThread5 = new P_Thread(p5); P_Thread pThread6 = new P_Thread(p6); pThread1.start(); pThread2.start(); pThread3.start(); pThread4.start(); pThread5.start(); pThread6.start(); C c1 = new C(myStack); C_Thread cThread = new C_Thread(c1); cThread.start(); } }
多生产与多消费:操作栈
package Third; public class Run { public static void main(String[] args) throws InterruptedException { MyStack myStack = new MyStack(); P p1 = new P(myStack); P p2 = new P(myStack); P p3 = new P(myStack); P p4 = new P(myStack); P p5 = new P(myStack); P p6 = new P(myStack); P_Thread pThread1 = new P_Thread(p1); P_Thread pThread2 = new P_Thread(p2); P_Thread pThread3 = new P_Thread(p3); P_Thread pThread4 = new P_Thread(p4); P_Thread pThread5 = new P_Thread(p5); P_Thread pThread6 = new P_Thread(p6); pThread1.start(); pThread2.start(); pThread3.start(); pThread4.start(); pThread5.start(); pThread6.start(); C r1 = new C(myStack); C r2 = new C(myStack); C r3 = new C(myStack); C r4 = new C(myStack); C r5 = new C(myStack); C r6 = new C(myStack); C r7 = new C(myStack); C r8 = new C(myStack); C_Thread cThread1 = new C_Thread(r1); C_Thread cThread2 = new C_Thread(r2); C_Thread cThread3 = new C_Thread(r3); C_Thread cThread4 = new C_Thread(r4); C_Thread cThread5 = new C_Thread(r5); C_Thread cThread6 = new C_Thread(r6); C_Thread cThread7 = new C_Thread(r7); C_Thread cThread8 = new C_Thread(r8); cThread1.start(); cThread2.start(); cThread3.start(); cThread4.start(); cThread5.start(); cThread6.start(); cThread7.start(); cThread8.start(); } }
通过管道进行线程间通信:字节流(见书)
通过管道进行线程间通信:字符流(见书)
实战:等待/通知之交叉备份
package Third; public class DBTools { volatile private boolean prevIsA = false; synchronized public void backupA() { try { while (prevIsA == true) { wait(); } for (int i = 0; i < 5; i++) { System.out.println("★★★★★"); } prevIsA = true; notifyAll(); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized public void backupB() { try { while (prevIsA == false) { wait(); } for (int i = 0; i < 5; i++) { System.out.println("☆☆☆☆☆"); } prevIsA = false; notifyAll(); } catch (InterruptedException e) { e.printStackTrace(); } } }
package Third; public class BackupA extends Thread { private DBTools dbtools; public BackupA(DBTools dbtools) { super(); this.dbtools = dbtools; } @Override public void run() { dbtools.backupA(); } }
package Third; public class BackupB extends Thread { private DBTools dbtools; public BackupB(DBTools dbtools) { super(); this.dbtools = dbtools; } @Override public void run() { dbtools.backupB(); } }
package Third; public class Run { public static void main(String[] args) { DBTools dbtools = new DBTools(); for (int i = 0; i < 20; i++) { BackupB output = new BackupB(dbtools); output.start(); BackupA input = new BackupA(dbtools); input.start(); } } }