并发包使用和解释

什么是并发包(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();

    }
}
原文地址:https://www.cnblogs.com/xiaozhang666/p/13176748.html