多线程案例|单例模式+阻塞式队列+定时器

文章目录

      • 单例模式
        • 饿汉模式
        • 懒汉模式
      • 阻塞式队列
      • 定时器

单例模式

某个类在整个进程的运行过程中,只允许有一个对象

  • 饿汉模式
    public class HungryMan {
        //一开始就初始化
        private static HungryMan instance = new HungryMan();
    
        private HungryMan() {
    
        }
        public static HungryMan getInstance() {
            return instance;
        }
    
        static class MyThread extends Thread {
            @Override
            public void run() {
                HungryMan ins1 = HungryMan.getInstance();
                System.out.println(ins1);
            }
        }
    
        public static void main(String[] args) {
            //单线程环境下
    //        singleton.HungryMan ins1 = singleton.HungryMan.getInstance();
    //        singleton.HungryMan ins2 = singleton.HungryMan.getInstance();
    //        singleton.HungryMan ins3 = singleton.HungryMan.getInstance();
    //
    //        System.out.println(ins1 == ins2); //true
    //        System.out.println(ins2 == ins3); //true
    
            //多线程环境下也是同一个对象
            MyThread[] threads = new MyThread[20];
            for (int i = 0; i < 20; i++) {
                threads[i] = new MyThread();
            }
    
            for (int i = 0; i < 20; i++) {
                threads[i].start();
            }
        }
    }
    
  • 懒汉模式
    public class LazyMan {
        private static volatile LazyMan instance = null;
    
        private  LazyMan() {
    
        }
    
        //单线程版,多线程环境下可能会出现问题
    //    public static LazyMan getInstance() {
    //        if (instance == null) {
    //            instance = new LazyMan();
    //        }
    //        return instance;
    //    }
    
        //法一二三四都是多线程版
    
        //法一:
        public static LazyMan getInstance1() {
                synchronized (LazyMan.class) {
                    if (instance == null) {
                    instance = new LazyMan();
                }
            }
            return instance;
        }
    
    //    //法二:
    //    public synchronized static LazyMan getInstance2() {
    //        if (instance == null) {
    //            instance = new LazyMan();
    //        }
    //        return instance;
    //    }
    //
    //    //法三:
    //    private static Object lock = new Object(); //在方法外面
    //    public static LazyMan getInstance3() {
    //        synchronized (lock) {
    //            if (instance == null) {
    //                instance = new LazyMan();
    //            }
    //        }
    //        return instance;
    //    }
    
        //二次判断-性能高
        public static LazyMan getInstance4() {
            if (instance == null) {
                synchronized (LazyMan.class) {
                    if (instance == null) {
                        instance = new LazyMan(); //有重排序问题,加入volatile
                    }
                }
            }
            return instance;
        }
    
    
    
        static class MyThread extends Thread {
            @Override
            public void run() {
                LazyMan ins = LazyMan.getInstance4();
                System.out.println(ins);
            }
        }
    
        public static void main(String[] args) {
    //        //单线程
    //        LazyMan ins1 = LazyMan.getInstance();
    //        LazyMan ins2 = LazyMan.getInstance();
    //        LazyMan ins3 = LazyMan.getInstance();
    //        System.out.println(ins1 == ins2); //true
    //        System.out.println(ins2 == ins3); //true
    
            //多线程环境下
            MyThread[] threads = new MyThread[20];
            for (int i = 0; i < 20; i++) {
                threads[i] = new MyThread();
            }
    
            for (int i = 0; i < 20; i++) {
                threads[i].start();
            }
        }
    }
    
  • 高效的多线程版本

多线程案例|单例模式+阻塞式队列+定时器_第1张图片

  • 为什么synchronized

    • 多线程情况下,原子性被破坏
  • 为什么二次判断

    • getInstance()会被调用很多次,而互斥的情况只在instance==null的时候发生
  • 为什么volatile

    • instance = new Singleton()有重排序问题

阻塞式队列

  • 自己实现

    public class MyArrayBlockingQueue {
        int[] array = new int[10];
        int front = 0; //只有消费者会改变
        int rear = 0; //只有生产者会改变
        int size = 0; //共享且会被修改
    
        synchronized void put(int value) throws InterruptedException {
            while (size == array.length) {
                wait();
            }
    
            array[rear] = value;
            rear = (rear + 1) % array.length;
            size++;
            System.out.println(size);
            notifyAll();
        }
    
        synchronized void put2(int value) throws InterruptedException {
            if (size == array.length) {
                this.wait(); 
            }
    
            array[rear] = value;
            rear = (rear + 1) % array.length;
            size++;
            System.out.println(size);
            notify();
        }
    
        synchronized int take() throws InterruptedException {
            if (size == 0) {
                this.wait();
            }
    
            int t = array[front];
            front = (front + 1) % array.length;
            size--;
            notify();
            return t;
        }
    
        static MyArrayBlockingQueue queue = new MyArrayBlockingQueue();
        static class Producer extends Thread {
            @Override
            public void run() {
                int j = 0;
                while (true) {
                    try {
                        queue.put(j);
                        j++;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            //多个生产者和多个消费者情况下
            MyBlockingArrayQueue.Producer producer1 = new MyBlockingArrayQueue.Producer();
            MyBlockingArrayQueue.Producer producer2 = new MyBlockingArrayQueue.Producer();
            MyBlockingArrayQueue.Producer producer3 = new MyBlockingArrayQueue.Producer();
            producer1.start();
            producer2.start();
            producer3.start();
            Thread.sleep(2*1000);
            while (true) {
                queue.take();
            }
        }
    }
    
  • 多线程案例|单例模式+阻塞式队列+定时器_第2张图片

  • 使用

    public class BlockingQueueDemo {
        public static void main(String[] args) throws InterruptedException {
            BlockingQueue<String> q1 = new ArrayBlockingQueue(15);
            BlockingQueue<String> q2 = new LinkedBlockingDeque<>();
            BlockingQueue<String> q3 = new PriorityBlockingQueue<>();
    
            q1.put("");
            String take = q1.take();
            System.out.println(take);
        }
    }
    

定时器

  • 自己实现

    import java.util.concurrent.TimeUnit;
    
    //定时器,10秒后打印一个happy
    public class SimpleTimer {
        interface SimpleTimerTask {
            void run();
        }
    
        //这个线程先 sleep delay时间后,再去执行任务
        static class Worker extends Thread {
            long delay;
            SimpleTimerTask task;
    
            Worker(SimpleTimerTask task, long delay) {
                this.task = task;
                this.delay = delay;
            }
    
            @Override
            public void run() {
                try {
                    Thread.sleep(delay);
                    task.run();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        void schedule(SimpleTimerTask task, long delay) {
            Worker worker = new Worker(task, delay);
            worker.start();
        }
    
        static class MyTask implements SimpleTimerTask {
            @Override
            public void run() {
                System.out.println("happy");
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            SimpleTimer timer = new SimpleTimer();
            MyTask task = new MyTask();
            timer.schedule(task, 10*1000);
            int i = 0;
            while (true) {
                System.out.println(i++);
                TimeUnit.SECONDS.sleep(1);
            }
        }
    }
    
  • 使用

    import java.util.Timer;
    import java.util.TimerTask;
    import java.util.concurrent.TimeUnit;
    
    public class TimerDemo {
        static class MyTask extends TimerTask {
            @Override
            public void run() {
                System.out.println("已经是 10 秒中后了");
            }
        }
        public static void main(String[] args) throws InterruptedException {
            TimerTask task = new MyTask();
            Timer timer = new Timer();
            timer.schedule(task, 10*1000);
            int i = 0;
            while (true) {
                System.out.println(i++);
                TimeUnit.SECONDS.sleep(1);
            }
        }
    }
    

你可能感兴趣的:(Java,多线程,java,设计模式,队列)