zoukankan      html  css  js  c++  java
  • 三个线程循环打印ABC10次的几种解决方法

    题目:有三个线程分别打印A、B、C,请用多线程编程实现,在屏幕打印10次ABC

    整体思路:该问题为三个线程的同步唤醒机制即ThreadA->ThreadB->ThreadC->ThreadA循环执行三个线程。

    public class MyThreadPrinter2 implements Runnable {
    
        private String name;
        private Object prev;
        private Object self;
        private Thread thread;
        
        public MyThreadPrinter2(String name,Object prev,Object self) {
            this.name=name;
            this.prev=prev;
            this.self=self;
            thread=new Thread(this,name);
        }
        
        @Override
        public void run() {
            // TODO Auto-generated method stub
            int count=10;
            while (count>0) {
                synchronized (prev) {
                    synchronized (self) {
                        System.out.print(name);
                        count--;
                        
                        self.notify();
                    }
                    try {
                        prev.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
        
        public static void main(String[] args) {
            Object aObject=new Object();
            Object bObject=new Object();
            Object cObject=new Object();
            
            MyThreadPrinter2 pa=new MyThreadPrinter2("A", cObject, aObject);
            MyThreadPrinter2 pb=new MyThreadPrinter2("B", aObject, bObject);
            MyThreadPrinter2 pc=new MyThreadPrinter2("c", bObject, cObject);
            
            pa.thread.start();
    //         try {
    //            Thread.sleep(1);
    //        } catch (InterruptedException e) {
    //            // TODO Auto-generated catch block
    //            e.printStackTrace();
    //        }
            pb.thread.start();
    //         try {
    //                Thread.sleep(10);
    //            } catch (InterruptedException e) {
    //                // TODO Auto-generated catch block
    //                e.printStackTrace();
    //            }
            pc.thread.start();
    //         try {
    //                Thread.sleep(10);
    //            } catch (InterruptedException e) {
    //                // TODO Auto-generated catch block
    //                e.printStackTrace();
    //            }
        }
    
    }

       运行后的打印结果为ACBACBACBACBACBACBACBACBACBACB。最后通过在start()中做延迟可以解决顺序不正确的问题。此方法用到两个锁,有些浪费资源。还有个问题就是打印后,程序还在运行。

    针对以上问题,可以采用sleep方法

    public class SleepExample extends Thread{
    
        private static int currentCount=0;
        
        public SleepExample(String name) {
            this.setName(name);
        }
        
        @Override
        public void run() {
            while (currentCount<30) {
                switch (currentCount%3) {
                case 0:
                    if ("A".equals(getName())) {
                        printAndIncrease();
                    }
                    break;
                    
                case 1:
                    if ("B".equals(getName())) {
                        printAndIncrease();
                    }
                    break;
                    
                case 2:
                    if ("C".equals(getName())) {
                        printAndIncrease();
                    }
                    break;
    
                default:
                    break;
                }
            }
        }
        
        private void printAndIncrease() {
            // TODO Auto-generated method stub
            print();
            increase();
        }
    
        private void increase() {
            currentCount++;        
        }
    
        private void print() {
            System.out.print(getName());
            if ("C".equals(getName())) {
                System.out.println();
            }
        }
        
        public static void main(String[] args) {
            new SleepExample("A").start();
            new SleepExample("B").start();
            new SleepExample("C").start();
        }
        
    }

    通过currentCount%3的余数控制线程打印A、B、C的顺序。也就是通过currentCount%3的余数来控制Thread.sleep()状态。
    使用synchronized,wait和notify

    public class PrintRunable implements Runnable{
    
        private LetterPrinter letterPrinter=null;
        
        private char letter=' ';
        
        public PrintRunable(LetterPrinter letterPrinter,char letter) {
            super();
            this.letterPrinter=letterPrinter;
            this.letter=letter;
        }
        
        @Override
        public void run() {
            // TODO Auto-generated method stub
            for (int i = 0; i < 10; i++) {
                synchronized (letterPrinter) {
                    while (letter!=letterPrinter.getLetter()) {
                        try {
                            letterPrinter.wait();//告知被调用的线程放弃管程进入休眠直到其他线程进入相同的管程并且调用notify()/notifyAll()
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                    
                    letterPrinter.Print();
                    letterPrinter.nextLetter();
                    letterPrinter.notifyAll();//恢复相同对象中第一个调用wait()的线程
                    
                }
            }
        }
    
    }

    字母打印顺序:

    public class LetterPrinter {
        private char letter='A';
        
        void Print(){
            System.out.print(letter);
            if ('C'==letter) {
                System.out.println();
            }
        }
        
        void nextLetter() {
            switch (letter) {
            case 'A':
                letter='B';
                break;
                
            case 'B':
                letter='C';
                break;
                
            case 'C':
                letter='A';
                break;
    
            default:
                break;
            }
        }
        
        /**
         * @return the letter
         */
        public char getLetter() {
            return letter;
        }
        
    }
    public class PrintThreadExample {    
        
        public static void main(String[] args) {
        
            LetterPrinter letterPrinter=new LetterPrinter();
            
            ExecutorService service=Executors.newFixedThreadPool(3);
            
            service.execute(new PrintRunable(letterPrinter, 'A'));//开启A线程
            service.execute(new PrintRunable(letterPrinter, 'B'));//开启B线程
            service.execute(new PrintRunable(letterPrinter, 'C'));//开启C线程
            service.shutdown();//结束程序
        }
    
    }

    使用Lock方法

    public class ABC {
    
        private static int state=0;
        
        public static void main(String[] args) {
            final Lock lock=new ReentrantLock();
            
            Thread A=new Thread(new Runnable() {
                public void run() {
                    while (state<=30) {
                        lock.lock();//get lock
                        if (state%3==0) {
                            System.out.print("A");
                            state++;
                        }
                        lock.unlock();//release lock
                    }
                }
            });
            
            Thread B=new Thread(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    while (state<=30) {
                        lock.lock();//get lock
                        if (state%3==1) {
                            System.out.print("B");
                            state++;
                        }
                        lock.unlock();//release lock
                    }
                }
            });
            
            Thread C=new Thread(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    while (state<=30) {
                        lock.lock();//get lock
                        if (state%3==2) {
                            System.out.print("C");
                            state++;
                        }
                        lock.unlock();//release lock
                    }
                }
            });
            
            A.start();
            B.start();
            C.start();        
        }
    
    }
  • 相关阅读:
    weblogic12c 2021.4.20 季度补丁 SPB
    一顿debug猛如虎,原来内存OOM
    JDK记录一下
    213. 打家劫舍 II-动态规划-中等
    5526. 最多可达成的换楼请求数目-回溯-困难
    1584. 连接所有点的最小费用-图/最小生成树-中等
    Java-泛型的限制
    Java-泛型-桥方法
    889. 根据前序和后序遍历构造二叉树-树-中等
    1109. 航班预订统计-差分数组-中等
  • 原文地址:https://www.cnblogs.com/chuji1988/p/4019287.html
Copyright © 2011-2022 走看看