• 三个线程循环打印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();        
        }
    
    }
  • 相关阅读:
    如何最大限度提高.NET的性能
    Webserivce简单安全验证
    一些NLP相关的JD,作参考
    拼多多的故事
    storm的一些相关文章
    这篇文章不错,仔细读读,码农晋升为技术管理者后,痛并快乐着的纠结内心
    protobuf的反射机制
    如何清理Docker占用的磁盘空间?
    经典面试题:浏览器是怎样解析CSS的?
    代码编辑器横评:为什么 VS Code 能拔得头筹
  • 原文地址:https://www.cnblogs.com/chuji1988/p/4019287.html
Copyright © 2020-2023  润新知