zoukankan      html  css  js  c++  java
  • 【面试题】关于线程交替的面试题

    线程交替打印的题经常出现,总结一下:

    一、两个线程交替打印0~100的奇偶数

    /*
     * 1.wait和notify都是Object类的方法。
     * 2.wait和notify必须要在synchronized代码块中执行,否则会抛异常。
     */
    public class WaitNotifyPrint {
    
        private static int count = 0;
        //两个线程竞争该对象锁
        private static final Object lock = new Object();
    
        public static void main(String[] args) throws InterruptedException {
            new Thread(new TurningRunner(), "偶数").start();
            new Thread(new TurningRunner(), "奇数").start();
        }
    
        //1. 拿到锁直接就打印。
        //2. 打印完,唤醒其他线程,自己就休眠。
        static class TurningRunner implements Runnable {
    
            @Override
            public void run() {
                while (count <= 100) {
                    synchronized (lock) {
                        //拿到锁就打印
                        System.out.println(Thread.currentThread().getName() + ":" + count++);
                        //打印完,唤醒其他线程
                        lock.notify();
                        //如果任务还没结束,就调用wait()让出当前的锁
                        if (count <= 100) {
                            try {
                                //自己休眠
                                lock.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }
    }
    

    二、生产者消费者

    /* 
     * 用EventStorage模拟仓库,Producer代表生产者,Consumer代表消费者,
     * 生产者和消费者共同对仓库进行协作。
     */
    public class ProducerConsumerModel {
        public static void main(String[] args) {
            //初始化仓库
            EventStorage eventStorage = new EventStorage();
            //用仓库初始化生产者
            Producer producer = new Producer(eventStorage);
            //用仓库初始化消费者
            Consumer consumer = new Consumer(eventStorage);
            //启动生产者和消费者
            new Thread(producer).start();
            new Thread(consumer).start();
        }
    }
    
    class Producer implements Runnable {
    
        private EventStorage storage;
    
        public Producer(
                EventStorage storage) {
            this.storage = storage;
        }
    
        @Override
        public void run() {
            //生产者往仓库中生产100个对象(此时消费者也在消费)
            for (int i = 0; i < 100; i++) {
                storage.put();
            }
        }
    }
    
    class Consumer implements Runnable {
    
        private EventStorage storage;
    
        public Consumer(
                EventStorage storage) {
            this.storage = storage;
        }
    
        @Override
        public void run() {
            //消费者循环消费仓库中的对象(此时生产者也在生产)
            for (int i = 0; i < 100; i++) {
                storage.take();
            }
        }
    }
    
    class EventStorage {
        private int maxSize;
        //用Date来模拟对象
        private LinkedList<Date> storage;
        //注意看构造方法定义仓库大小为10,并且用LinkedList来存储对象
        public EventStorage() {
            maxSize = 10;
            storage = new LinkedList<>();
        }
        public synchronized void put() {
            //仓库满了就休眠
            while (storage.size() == maxSize) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //仓库没满就添加并通知消费者
            storage.add(new Date());
            System.out.println("仓库里有了" + storage.size() + "个产品。");
            notify();
        }
        public synchronized void take() {
            //仓库空了就休眠
            while (storage.size() == 0) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //没空就取数据,poll方法代表检索并删除并通知生产者
            System.out.println("拿到了" + storage.poll() + ",现在仓库还剩下" + storage.size());
            notify();
        }
    }
    

    三、交替打印ABC

    方法一、synchronized

    public class ABC {
        public static class ThreadPrinter implements Runnable {
            private String name;
            private Object prev;
            private Object self;
            private ThreadPrinter(String name,Object prev,Object self){
                this.name=name;
                this.prev=prev;
                this.self=self;
            }
    
            @Override
            public void run() {
                while (true){
                    synchronized (prev){
                        synchronized (self){
                            System.out.println(name);
                            self.notifyAll();
                        }
                        try{
                            prev.wait();
                        }catch (InterruptedException e){
                            e.printStackTrace();
                        }
                    }
    
                }
            }
    
            public static void main(String[] args) throws InterruptedException {
                Object a = new Object();
                Object b = new Object();
                Object c = new Object();
    
                ThreadPrinter pa=new ThreadPrinter("A",c,a);
                ThreadPrinter pb=new ThreadPrinter("B",a,b);
                ThreadPrinter pc=new ThreadPrinter("C",b,c);
                //保证ABC顺序执行
                new Thread(pa).start();
                Thread.sleep(10);
                new Thread(pb).start();
                Thread.sleep(10);
                new Thread(pc).start();
                Thread.sleep(10);
    
            }
        }
    }
    

    方法二、ReentrantLock

    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class ABC2 {
        private static Lock lock= new ReentrantLock();
        private static int state=0;
        static class ThreadA extends Thread{
            @Override
            public void run() {
                while(true) {
                    try {
                        lock.lock();
                        while (state % 3 == 0) {
                            System.out.println("A");
                            state++;
                        }
                    } finally {
                        lock.unlock();
                    }
                }
            }
        }
        static class ThreadB extends Thread{
            @Override
            public void run() {
                while(true) {
                    try {
                        lock.lock();
                        while (state % 3 == 1) {
                            System.out.println("B");
                            state++;
                        }
                    } finally {
                        lock.unlock();
                    }
                }
            }
        }
        static class ThreadC extends Thread{
            @Override
            public void run() {
                while(true) {
                    try {
                        lock.lock();
                        while (state % 3 == 2) {
                            System.out.println("C");
                            state++;
                        }
                    } finally {
                        lock.unlock();
                    }
                }
            }
        }
    
        public static void main(String[] args) {
            new ThreadA().start();
            new ThreadB().start();
            new ThreadC().start();
        }
    }
    

    方法三、信号量

    public class ABC3 {
        private static Semaphore A =new Semaphore(1);
        private static Semaphore B =new Semaphore(0);
        private static Semaphore C =new Semaphore(0);
    
        static class ThreadA extends Thread{
            @Override
            public void run() {
                try {
                    while(true){
                        A.acquire();
                        System.out.println("A");
                        B.release();
                    }
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
        }
    
        static class ThreadB extends Thread{
            @Override
            public void run() {
                try {
                    while(true){
                        B.acquire();
                        System.out.println("B");
                        C.release();
                    }
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
        }
        static class ThreadC extends Thread{
            @Override
            public void run() {
                try {
                    while(true){
                        C.acquire();
                        System.out.println("C");
                        A.release();
                    }
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
        }
        public static void main(String[] args) throws InterruptedException {
            new ThreadA().start();
            new ThreadB().start();
            new ThreadC().start();
        }
    }
    
  • 相关阅读:
    linux 运维工程师发展路线
    Linux 系统巡检常用命令
    svn 服务器部署
    linux python2.x 升级python3.x
    201871010131张兴盼《面向对象程序设计(java)》第二周学习总结 201871010131
    201871010131张兴盼《面向对象程序设计(java)》第一周学习总结 201871010131
    《2019面向对象程序设计(java)课程学习进度条》 201871010131
    张兴盼201871010131 《面向对象程序设计(java)》第六、七周学习总结 201871010131
    201871010131张兴盼《面向程序设计(java)》第四周学习总结 201871010131
    201871010131张兴盼《面向对象程序设计(java)》第八周学习总结 201871010131
  • 原文地址:https://www.cnblogs.com/KeleLLXin/p/14612046.html
Copyright © 2011-2022 走看看