zoukankan      html  css  js  c++  java
  • 并发包使用和解释

    什么是并发包(JDK1.5提出):收集了各种专门在多线程情况下使用,并且可以保证线程安全的一些类

    CopyOnWriteArrayList

    普通并发下的List

    public class CopyOnWrite {
        static List<Integer> list = new ArrayList<>();
        public static void main(String[] args) {
            demo1();
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(list.size());
        }
    
        public static void demo1(){
            new Thread(){
                @Override
                public void run() {
                    for (int i = 0; i < 10000; i++) {
                        list.add(i);
                    }
                }
            }.start();
    
            new Thread(){
                @Override
                public void run() {
                    for (int i = 0; i < 10000; i++) {
                        list.add(i);
                    }
                }
            }.start();
        }
    }

    结果:

     解决方法使用:CopyOnWriteArrayList是线程安全的

    public static CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();

    Set使用CopyOnWriteArraySet

     public static CopyOnWriteArraySet<Integer> set = new CopyOnWriteArraySet<>();

    MapConcurrentHashMap

    public static Hashtable<Integer, Integer> map = new Hashtable<>();

    对于HaseTable

    但是HashTable有两个性能上的问题:
    a.无脑加锁,无论是添加,删除,获取都加锁,并使用同一个锁对象,导致性能极其低下
    b.HashTable添加是全局锁,有且仅有一个线程可以操作HashTable,导致性能极其低下

    多线程并发问题关键字

    自从JDK5发布以来,在java.util.concurrent包中提供了一些非常有用的辅助类来帮助我们进行并发编程,下面就介绍一下这些辅助类中的Semaphore、CyclicBarrier、CountDownLatch以及Exchanger的相关用法

    1.CountDownLatch

      CountDownLatch可以实现类似计数器的功能,计数器的初始值为指定的线程的数量,每当一个线程完成了自己的任务,计数器的值就会减1,当计数器的值达到了0时,它表示所有的线程都完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。构造器上的计数值实际上就是闭锁需要等待的线程数量,这个值只能被设置一次,而且CountDownLatch没有提供任何机制去重新设置这个值。

    构造方法:
        public CountDownLatch(int count);指定计数的线程
    成员方法:
        public void await();让当前线程等待
        public void countDown();减少需要等待的线程数量  
    public class BengTest {
        static CountDownLatch downLatch = new CountDownLatch(1);
        static CountDownLatch downLatch2 = new CountDownLatch(1);
        public static void main(String[] args) {
            demo1();
        }
    
        public static void demo1(){
            new Thread(){
                @Override
                public void run() {
                    System.out.println("起床");
                    downLatch.countDown();
                }
            }.start();
            new Thread(){
                @Override
                public void run() {
                    try {
                        downLatch.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("洗脸");
                    downLatch2.countDown();
                }
            }.start();
            new Thread(){
                @Override
                public void run() {
                    try {
                        downLatch2.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("出门");
                }
            }.start();
        }
    
    }

    2.CyclicBarrier

    CyclicBarrier直译过来叫做内存屏障,它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续下面的业务。

    构造方法:
        public CyclicBarrier(int parties, Runnable barrierAction);
        参数1:parties表示这组线程的数量!
        参数2:barrierAction 表示一组线程都到达之后需要执行的任务!     
    
    成员方法:
        public int await(); 让当前线程阻塞
    /**
     * @program: study_java
     * @description: test
     * @author: xiaozhang6666
     * @create: 2020-06-22 13:44
     **/
    public class BengTest {
        static CyclicBarrier cyclicBarrier = new CyclicBarrier(2, new Runnable() {
            @Override
            public void run() {
                System.out.println("触发屏障后程序");
            }
        });
        public static void main(String[] args) {
            demo2();
        }
    
        public static void demo2(){
            new Thread(){
                @Override
                public void run() {
                    System.out.println("屏障1");
                    try {
                        cyclicBarrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            }.start();
            new Thread(){
                @Override
                public void run() {
                    System.out.println("屏障2");
                    try {
                        cyclicBarrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            }.start();
        }
    
    }
    3.Semaphore

    emaphore是计数信号量,是操作系统中的一个概念,经常用于限制获取某种资源的线程数量,在new 这个类的时候需要给这个类传递一个参数permits,这个参数是整数类型,这个参数的意思是同一时间内,最多允许多少个线程同时执行acquire方法和release方法之间的代码,如果方法acquire没有参数则默认是一个许可。

    构造方法:
    public Semaphore(int permits);
            参数permits称为许可证,即最大的线程并发数量
    成员方法:
    public void acquire(); 表示获取许可证
    public void release(); 释放许可证   
    package day17.package_homework;
    
    import java.util.concurrent.BrokenBarrierException;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.CyclicBarrier;
    import java.util.concurrent.Semaphore;
    
    /**
     * @program: study_java
     * @description: test
     * @author: xiaozhang6666
     * @create: 2020-06-22 13:44
     **/
    public class BengTest {
        static Semaphore semaphore = new Semaphore(1);
    
        public static void main(String[] args) {
            demo3();
        }
    
        public static void demo3() {
            new Thread() {
                @Override
                public void run() {
                    try {
                        semaphore.acquire();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程一开始");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程一结束...");
                    semaphore.release();
                }
            }.start();
            new Thread() {
                @Override
                public void run() {
                    try {
                        semaphore.acquire();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程二开始");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程二结束...");
                    semaphore.release();
                }
            }.start();
            new Thread() {
                @Override
                public void run() {
                    try {
                        semaphore.acquire();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程三开始");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程三结束...");
                    semaphore.release();
                }
            }.start();
        }
    
    }

    4.Exchanger

    Exchanger是用于线程间协作的工具类,用于线程间的数据交换,它提供一个同步点,在这个同步点两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据, 如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。

    构造方法:
        public Exchanger();
    成员方法:
        public V exchange(V x);//交换数据
    public class ThreadA extends Thread {
        private Exchanger<String> exchanger;
        public ThreadA(Exchanger<String> exchanger){
            this.exchanger = exchanger;
        }
    
        @Override
        public void run() {
            try {
                //线程A给线程B发信息
                System.out.println("线程A给线程B发信息...");
                String exchange = exchanger.exchange("AAAAAAAAAAAA");
                System.out.println("同时获取到线程B的回信:"+exchange);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    public class ThreadB extends Thread {
        private Exchanger<String> exchanger;
        public ThreadB(Exchanger<String> exchanger){
            this.exchanger = exchanger;
        }
    
        @Override
        public void run() {
            try {
                //线程B给线程A发信息
                System.out.println("线程B给线程A发信息...");
                String exchange = exchanger.exchange("BBBBBBBBBBBBBBBB");
                System.out.println("同时获取到线程A的回信:"+exchange);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    
    public class TestDemo {
        public static void main(String[] args) {
            //1.创建Exchanger
            Exchanger<String> exchanger = new Exchanger<String>();
    
            //2.创建线程AB
            ThreadA a = new ThreadA(exchanger);
            ThreadB b = new ThreadB(exchanger);
    
            //3.开启线程A
            a.start();
            b.start();
    
        }
    }
  • 相关阅读:
    DO语句与SELECT语句,HANDLER语句
    Mysql 删除语句
    Mysql 调用存储过程的两种方式
    Mysql tablespace
    忘记Mysql登录密码
    Mysql 全文索引
    Mysql手册—SQLStatementSyntax
    Mysql手册—基本规范与数据类型
    Mysql常用函数列举
    真三 典伟的帅气
  • 原文地址:https://www.cnblogs.com/xiaozhang666/p/13176748.html
Copyright © 2011-2022 走看看