• 《Java多线程编程核心技术》读后感(十)


    一生产一消费:操作栈

    本实例是使生产者向堆栈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();
            }
        }
    
    }

  • 相关阅读:
    DFS-B
    DFS/BFS-A
    DFS-回溯与剪枝-C
    BFS-八数码问题与状态图搜索
    PTA-1003 我要通过!
    二分-G
    二分-F
    二分-E
    二分-D
    二分-C
  • 原文地址:https://www.cnblogs.com/Michael2397/p/7856478.html
Copyright © 2020-2023  润新知