目录
JUC
java.util.concurrent 下的类就叫 JUC 类,JUC 下典型的类有:
 ReentrantLock
 Semaphore
 CountDownLatch
 CyclicBarrier
ReentrantLock:可重入锁
Semaphore:信号量(可以实现限流)
-acquire:获得令牌
 -release:发布令牌
import java.time.LocalDateTime;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/**
 * 信号量(可以实现限流)
 */
public class SemaphoreDemo1 {
    public static void main(String[] args) {
        //创建线程池
        ExecutorService service= Executors.newFixedThreadPool(5);
        //创建信号量
        Semaphore semaphore=new Semaphore(2);
        //统一任务的定义
        Runnable runnable=new Runnable() {
            @Override
            public void run() {
                Thread currThread=Thread.currentThread();//得到执行此任务的线程
                System.out.println("进入线程:"+currThread.getName());
                try {
                    //获取令牌
                    semaphore.acquire();//如果没有可用令牌,线程会阻塞在当前位置
                    System.out.println(currThread.getName()+":得到了令牌|Time"+
                             LocalDateTime.now());
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    System.out.println(currThread.getName()+":释放令牌|Time"+
                            LocalDateTime.now());
                    //释放令牌
                    semaphore.release();
                }
            }
        };
        //定义新线程执行任务
        service.submit(runnable);
        //定义新线程执行任务
        service.submit(runnable);
        //定义新线程执行任务
        service.submit(runnable);
        //定义新线程执行任务
        service.submit(runnable);
        //定义新线程执行任务
        service.submit(runnable);
    }
}
 
CountDownLatch:计数器:判断线程池的任务是否已经全部执行完
-countDown:计数器-1
 -await:阻塞等待,所有的任务全部执行完(等待CountDownLatch=0后继续执行后面的代码)
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
 * 计数器使用
 */
public class CountDownLatchDemo1 {
    public static void main(String[] args) throws InterruptedException {
        //创建计数器
        CountDownLatch countDownLatch = new CountDownLatch(5);
        //创建新线程执行任务
        for (int i = 1; i < 6; i++) {
            new Thread(() -> {
                Thread currThread = Thread.currentThread();
                System.out.println(currThread.getName() + "开始起跑");
                try {
                    //跑步所用时间
                    int runTime = (1 + new Random().nextInt(5));
                    TimeUnit.SECONDS.sleep(runTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(currThread.getName() + ":到达终点,用时:");
                countDownLatch.countDown();
            }, "选手-" + i).start();
        }
        countDownLatch.await();
        System.out.println("宣布比赛结果");
    }
}
 
CyclicBarrier:循环屏障(线程分组的阻塞)
-await:计数器-1,判断当前计数器是否为0,如果是0,冲破栅栏执行之后的代码;否则阻塞等待,直到栅栏被冲坡。
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 * 循环屏障
 */
public class CyclicBarrierDemo1 {
    public static void main(String[] args) {
        //循环屏障
        CyclicBarrier cyclicBarrier=new CyclicBarrier(5, new Runnable() {
            @Override
            public void run() {
                System.out.println("计数器为0了");
            }
        });
        //创建线程池
        ExecutorService service=Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            int finalI = i;
            service.submit(()->{
                Thread currThread=Thread.currentThread();
                System.out.println("执行线程:"+currThread.getName());
                try {
                    Thread.sleep(500* finalI);
                    cyclicBarrier.await();//执行阻塞等待(计数器-1,阻塞等待,直到循环屏障的计数器为0的时候,在执行后面的代码)
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
                System.out.println("执行线程完成:"+currThread.getName());
            });
        }
    }
}
 
非线程安全容器
Java 标准库中很多都是线程不安全的. 这些类可能会涉及到多线程修改共享数据, 又没有任何加锁措施.
 ArrayList
 LinkedList
 HashMap
 TreeMap
 HashSet
 TreeSet
 StringBuilder
线程安全容器
Vector (不推荐使用)
 Hashtable (不推荐使用,性能低)
 ConcurrentHashMap
 StringBuffer
HashMap知识点
1.底层数据结构实现
 2.负载因子(扩充因子作用)
 3.哈希冲突是如何解决的
 4.是否是线程安全的?为什么?
 首先 HashMap 是线程不安全的,其主要体现:
 在 jdk 1.7 中,在多线程环境下,扩容时因为采用头插法,会造成死循环和数据覆盖。
 在 jdk 1.8 中,在多线程环境下,会发生数据覆盖的情况。
5.如何解决线程安全问题?加锁/ConcurrentHashMap
 6.ConcurrentHashMap如何实现线程安全?










