zoukankan      html  css  js  c++  java
  • 多线程与高并发4 LockSupport、3道题

    (1)LockSupport

    这儿parkunpark其实实现了waitnotify的功能,不过还是有一些差别的。

    1. park不需要获取某个对象的锁
    2. 因为中断的时候park不会抛出InterruptedException异常,所以需要在park之后自行判断中断状态,然后做额外的处理
    package dayo4;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.LockSupport;
    
    /**
     * @author: zdc
     * @date: 2020-03-27
     */
    public class _1LockSupport {
        public static void main(String[] args) throws InterruptedException {
            Thread t = new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    System.out.println(i);
                    if(i==5)
                        LockSupport.park();
                }
            });
            t.start();
            TimeUnit.SECONDS.sleep(2);
            LockSupport.unpark(t);
        }
    }

    (2)题目1

      实现一个容器,提供两个方法,add,size 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,当个数到5个时,线程2给出提示并结束

    • 1
    package dayo4;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @author: zdc
     * @date: 2020-03-27
     */
    public class MyContainer1<T> {
        private List<T> list = new ArrayList<>();
    
        public void add(T t) {
            list.add(t);
        }
    
        public int size() {
            return list.size();
        }
    
        public static void main(String[] args) {
            Object lock = new Object();
            MyContainer1<String> container = new MyContainer1<>();
            new Thread(() -> {
                synchronized (lock) {
                    if (container.size() != 5) {
                        try {
                            lock.wait();      //1
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("元素已经加到5");
                    lock.notify();
                }
            }, "t1").start();
    
            new Thread(() -> {
                synchronized (lock) {
                    for (int i = 0; i < 10; i++) {
                        container.add("element" + i);
                        if (container.size() == 5) {
                            //注意线程2要wait 这样线程1才会活的执行权 否则只是线程2只是被notify 但并没有获得cpu执行权.wait会释放锁,
                            // notify仅仅只是通知,不释放锁)notify并不释放锁,只是告诉调用过wait方法的线程可以去参与获得锁的竞争了,
                            // 但不是马上得到锁,因为锁还在别人手里,别人还没释放
                            lock.notify();
                            try {
                                lock.wait();//线程1释放锁
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println(i+1);
                    }
                }
            }, "t2").start();
        }
    }
    • 2

      CountDownLatch

    public class MyContainer2<T> {
        private List<T> list = new ArrayList<>();
    
        public void add(T t) {
            list.add(t);
        }
    
        public int size() {
            return list.size();
        }
    
        public static void main(String[] args) {
            CountDownLatch countDownLatch = new CountDownLatch(1);
            MyContainer1<String> container = new MyContainer1<>();
            new Thread(() -> {
                if (container.size() != 5) {
                    try {
                        countDownLatch.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("元素已经加到5");
    
            }
                    , "t1").start();
    
            new Thread(() -> {
                    for (int i = 0; i < 10; i++) {
                        container.add("element" + i);
                        if (container.size() == 5) {
                         countDownLatch.countDown();
                            try {
                                countDownLatch.await(); //这儿存疑 因为此时N=0了 为什么线程t2会停住一下下呢?
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println(i + 1);
    
                    }
    
            }, "t2").start();
        }
    }
    • 3

      LockSupport

    package dayo4;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.locks.LockSupport;
    
    /**
     * @author: zdc
     * @date: 2020-03-27
     */
    public class MyContainer2<T> {
        private List<T> list = new ArrayList<>();
    
        public void add(T t) {
            list.add(t);
        }
    
        public int size() {
            return list.size();
        }
    
        static Thread t2 = null;  //
        public static void main(String[] args) {
            CountDownLatch countDownLatch = new CountDownLatch(1);
            MyContainer1<String> container = new MyContainer1<>();
    
            Thread t1 = new Thread(() -> {
                if (container.size() != 5) {
                    LockSupport.park();
                }
                System.out.println("元素已经加到5");
                LockSupport.unpark(t2);
            }
                    , "t1");
            t1.start();
    
            t2 = new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    container.add("element" + i);
                    if (container.size() == 5) {
                        LockSupport.unpark(t1);
                        LockSupport.park();
                    }
                    System.out.println(i + 1);
                }
    
            }, "t2");
            t2.start();
        }
    }

    (3)题目2

    两个线程,分别打印AB,其中线程A打印1,2,3,4,5 B线程打印A,B,C....使之出现A1B2..... 的效果。

    • wait notify
    public class Demo {
        public static void main(String[] args) {
            Character[] characters1 = {'1', '2', '3', '4', '5'};
            Character[] characters2 = {'A', 'B', 'C', 'D', 'E'};
            Object lock = new Object();
             new Thread(() -> {
    
                for (int i = 0; i < characters1.length; i++) {
                    synchronized (lock) {
                        System.out.println(characters1[i]);
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        lock.notify();
                    }
                }
            }, "t1").start();
            new Thread(() -> {
                for (int i = 0; i < characters2.length; i++) {
                    synchronized (lock){
                        System.out.println(characters2[i]);
                        lock.notify();
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }, "t2").start();
        }
    }
    • 2  ReentrantLock
    public class Demo {
    public static void main(String[] args) {
    Character[] characters1 = {'1', '2', '3', '4', '5'};
    Character[] characters2 = {'A', 'B', 'C', 'D', 'E'};
    ReentrantLock lock = new ReentrantLock();
    Condition condition1 = lock.newCondition();
    Condition condition2 = lock.newCondition();
    new Thread(() -> {
    lock.lock();
    for (int i = 0; i < characters1.length; i++) {
    System.out.println(characters1[i]);
    condition2.signal();
    try {
    condition1.await();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    condition2.signal(); //循环题结束后t1,t2最后肯定有一个没醒过来的所以要唤醒
    lock.unlock();
    }, "t1").start();
    new Thread(() -> {
    lock.lock();
    for (int i = 0; i < characters2.length; i++) {
    System.out.println(characters2[i]);
    condition1.signal();
    try {
    condition2.await();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    condition1.signal();
    lock.unlock();
    }, "t2").start();
    }
    }

    (4)题目3

      写一个固定容量同步容器,拥有put和get方法,以及getCount方法,能够支持多个生产者和多个消费者线程拥塞调用。

    1)使用synchronized锁的notify、notifyAll来实现

    生成消费交互

    public class MyContainer<T> {
       private static int count=0; //生产的数
        private final List<T> list = new ArrayList<>();
        //最大容量
        public static final int MAX_CAPACITY = 10;
        public static final int FIRST= 0;
        public synchronized void put(T t){
            while (list.size()==MAX_CAPACITY){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("生产了"+list.add(t)+":"+t);
            this.notifyAll();
        }
        public synchronized void remove(){
            while (list.size()==0){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("消费了:"+list.remove(FIRST));
            this.notifyAll();
        }
    
        public static void main(String[] args) {
    
            MyContainer<String> container = new MyContainer<>();
            for (int i = 0; i < 10; i++) {
                //启动十个消费线程
                new Thread(container::remove).start();
                //启动20个生产线程
                new Thread(()->{
                    container.put(""+count++);
                }).start();
            }
        }
    }

    无线生产 消费

    public class MyContainer {
        private static int count = 1; //生产的数
        private final List list = new ArrayList<>();
        //最大容量
        public static final int MAX_CAPACITY = 10;
        public static final int FIRST = 0;
    
        public synchronized void put() {
            while (true){
                while (list.size() == MAX_CAPACITY) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                list.add(count++);
                System.out.println("线程" + Thread.currentThread().getName() + "生产了" + ":" + count);
                this.notifyAll();
            }
        }
    
        public synchronized void remove() {
            while (true){
                while (list.size() == 0) {
                    try {
                        System.out.println("等待生产");
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("消费了:" + list.remove(FIRST));
                this.notifyAll();
            }
    
        }
    
        public static void main(String[] args) {
    
            MyContainer container = new MyContainer();
            for (int i = 0; i < 10; i++) {
                //启动5个消费线程
                new Thread(container::remove, i + "").start();
                //启动20个生产线程
                new Thread(() -> {
                    container.put();
                }, i + "").start();
            }
        }
    }

    2)使用ReentrantLock锁的notify、notifyAll来实现

    public class _MyContainer2{
        private static int count = 1; //生产的数
        private final List list = new ArrayList<>();
        //最大容量
        public static final int MAX_CAPACITY = 10;
        public static final int FIRST = 0;
        private final Lock lock = new ReentrantLock();
        private final Condition consumer= lock.newCondition();
        private final Condition producer= lock.newCondition();
    
        public  void put() {
            while (true) {
                lock.lock();
                while (list.size() == MAX_CAPACITY) {
                    try {
                        producer.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                list.add(count++);
                System.out.println("线程" + Thread.currentThread().getName() + "生产了" + ":" + count);
                consumer.signalAll();
            }
        }
    
        public void remove() {
            while (true) {
                lock.lock();
                while (list.size() == 0) {
                    try {
                        consumer.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("消费了:" + list.remove(FIRST));
                producer.signalAll();
            }
        }
    
        public static void main(String[] args) {
    
            _MyContainer1 container = new _MyContainer1();
            for (int i = 0; i < 1; i++) {
                //启动5个消费线程
                new Thread(container::remove, i + "").start();
                //启动20个生产线程
                new Thread(() -> {
                    container.put();
                }, i + "").start();
            }
        }
    }

    3)直接使用BlockingQueue实现

    package dayo4;
    
    import java.util.ArrayList;
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.BlockingDeque;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.LinkedBlockingDeque;
    
    /**
     * @author: zdc
     * @date: 2020-03-30
     */
    public class _MyContainer3 {
        private static int count = 1; //生产的数
        public static final int MAX_CAPACITY = 10;
        public static final int FIRST = 0;
        private BlockingQueue queue = new LinkedBlockingDeque();//无界对象   Integer.MAX_VALUE
    
        public void put(){
            while (true){
                try {
                    queue.put(count++);
                    System.out.println("线程" + Thread.currentThread().getName() + "生产了" + ":" + count);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
        }
        public void remove(){
            while (true){
                Integer num = null;
                try {
                    num = (Integer)queue.take(); //take
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程" + Thread.currentThread().getName() + "消费了"+num);
            }
    
        }
    
        public static void main(String[] args) {
            _MyContainer3 container = new _MyContainer3();
            for (int i = 0; i < 10; i++) {
                //启动5个消费线程
                new Thread(container::remove, i + "").start();
                //启动20个生产线程
                new Thread(() -> {
                    container.put();
                }, i + "").start();
            }
        }
    }
  • 相关阅读:
    SVN菜单说明
    Jabber Software:Jabber-NET、agsXMPP与Wilefire[转]
    nuget的使用总结
    SET QUOTED_IDENTIFIER ON
    SET ANSI_NULLS ON
    SQL Server性能杀手
    How to open .ccproj in VS2010?
    Bios里,把SATA Mode Selection改为AHCI无法启动
    [转]内嵌WORD/OFFICE的WINFORM程序——DSOFRAMER使用小结
    使用EF连接现有数据库
  • 原文地址:https://www.cnblogs.com/zdcsmart/p/12582818.html
Copyright © 2011-2022 走看看