JAVA并发编程

目录

一·线程池

1、为什么使用线程池

2、使用线程池

3、jdk已提供的线程池

①FixedThreadPool

②CachedThreadPool

③ScheduledThreadPool

④比较

二·ThreadLocal

2、使用场景 ​

①每个线程独享变量

②避免传参麻烦每个线程保存全局变量

2、用法总结​

3、好处​

4、原理

①ThreadLocal

②TheadLocalMap

5、使用注意点

①内存泄漏

②避免

三·锁

1、Lock

①简介

②使用

2、锁的分类

①乐观锁和悲观锁

②可重入锁

③公平锁与非公平锁

④共享锁和排它锁

⑤锁的升级以及降级

⑥自旋锁和阻塞锁

⑥可中断锁

四·atomic

①介绍

②AtomicInteger

③AtomicArray

④Atomic*Reference

⑤普通变量升级为原子功能变量

⑥累加器

五·CAS

①简介及原理

②缺点

六·final

①不变性

②作用

③栈封闭技术

七·并发集合

①并发容器概览

②集合历史

1、Vectory线程安全的List但是并发时效率不行

2、Hashtable线程安全的Map但是并发时效率不行

3、ArrayList线程不安全的

4、HashMap线程不安全的

③Map

1、jdk1.7 hashMap死循环造成CPU100%

2、hashMap 1.7和1.8结构图和特点

3、ConcurrentHashMap

④CopyOnWriteArrayList

⑤并发队列

1、阻塞队列

2、非阻塞队列

八·并发流程

①countDownLatch

②semaphore

③condition

④CyclicBarrier

九·AQS

①简介

②用法及源码

1、CountDownLatch

3、ReentrantLock

十·Future


一·线程池

1、为什么使用线程池

2、使用线程池

拒绝策略

AbortPolicy 丢弃任务并抛出RejectedExecutionException异常(默认)
CallerRunsPolicy 由调用线程处理该任务
DiscardOldestPolicy 丢弃队列最前面的任务然后重新尝试执行该任务,重复此过程
DiscardPolicy 丢弃被拒绝的任务


3、jdk已提供的线程池

①FixedThreadPool

 

特点:固定数量线程池

ExecutorService executorService = Executors.newFixedThreadPool(4);

 

源码:

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

核心线程数已最大线程数一致,即:线程池初始化核心线程后就不会再创建新线程了。

队列为链表阻塞队列,无界队列,当请求一多可能造成OOM。

②CachedThreadPool

 

特点:可缓存的线程池、具有自动回收多余线程的功能

ExecutorService executorService = Executors.newCachedThreadPool();

源码:

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

当有请求过来时就直接新建线程去执行,当线程执行完毕,存活为60s后开始回收线程。核心线程数为0,最大线程数为Integer的最大值,队列为直接交接队列即不会存储数据的。

③ScheduledThreadPool

特点:支持定时及周期性执行任务

ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(10);
//        threadPool.schedule(new Task(), 5, TimeUnit.SECONDS);
        threadPool.scheduleAtFixedRate(new Task(), 1, 3, TimeUnit.SECONDS);

④比较

·ThreadLocal

2、使用场景
 

①每个线程独享变量

 

public class ThreadLocalNormalUsage05 {

    public static ExecutorService threadPool = Executors.newFixedThreadPool(10);

    public static void main(String[] args) {
        for (int i = 0; i < 1000; i++) {
            int finalI = i;
            threadPool.submit(() -> {
                String date = new ThreadLocalNormalUsage05().date(finalI);
                System.out.println(date);
            });
        }
        threadPool.shutdown();
    }

    public String date(int seconds) {
        //参数的单位是毫秒,从1970.1.1 00:00:00 GMT计时
        Date date = new Date(1000 * seconds);
//        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat dateFormat = ThreadSafeFormatter.dateFormatThreadLocal .get();
        return dateFormat.format(date);
    }
}

class ThreadSafeFormatter {
    public static ThreadLocal<SimpleDateFormat> dateFormatThreadLocal = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };
}

 

②避免传参麻烦每个线程保存全局变量

public class ThreadLocalNormalUsage06 {

    public static void main(String[] args) {
        new Service1().process("");

    }
}

class Service1 {

    public void process(String name) {
        User user = new User("超哥");
        UserContextHolder.holder.set(user);
        new Service2().process();
    }
}

class Service2 {

    public void process() {
        User user = UserContextHolder.holder.get();
        ThreadSafeFormatter.dateFormatThreadLocal.get();
        System.out.println("Service2拿到用户名:" + user.name);
        new Service3().process();
    }
}

class Service3 {

    public void process() {
        User user = UserContextHolder.holder.get();
        System.out.println("Service3拿到用户名:" + user.name);
        UserContextHolder.holder.remove();
    }
}

class UserContextHolder {

    public static ThreadLocal<User> holder = new ThreadLocal<>();


}

class User {

    String name;

    public User(String name) {
        this.name = name;
    }
}


2、用法总结

3、好处

4、原理

①ThreadLocal

②TheadLocalMap

5、使用注意点

①内存泄漏

②避免

·锁

1、Lock

①简介

②使用

2、锁的分类

①乐观锁和悲观锁

乐观锁:非互斥同步锁

悲观锁:互斥同步锁

②可重入锁

无需释放锁即可再次获得锁synchornized也是

③公平锁与非公平锁

④共享锁和排它锁

JAVA中的读写锁

private static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
private static ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
private static ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();

应用

private static void read() {
    readLock.lock();
    try {
        System.out.println(Thread.currentThread().getName() + "得到了读锁,正在读取");
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        System.out.println(Thread.currentThread().getName() + "释放读锁");
        readLock.unlock();
    }
}

private static void write() {
    writeLock.lock();
    try {
        System.out.println(Thread.currentThread().getName() + "得到了写锁,正在写入");
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        System.out.println(Thread.currentThread().getName() + "释放写锁");
        writeLock.unlock();
    }
}

写锁线程造成饥饿

ReentrantReadWriteLock的实现:

源码分析

公平锁

都不能插队,如果队列中你就需要等待

非公平锁

⑤锁的升级以及降级

可以降及不可以升级,即可以由写锁降为读锁并释放写锁。不能由读锁升级为写锁,因为能多读或一写升级容易造成死锁。

写锁降级为读锁

private static void writeDowngrading() {
    writeLock.lock();
    try {
        System.out.println(Thread.currentThread().getName() + "得到了写锁,正在写入");
        Thread.sleep(1000);
        readLock.lock();
        System.out.println("在不释放写锁的情况下,直接获取读锁,成功降级");
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        readLock.unlock();
        System.out.println(Thread.currentThread().getName() + "释放写锁");
        writeLock.unlock();
    }
}
public static void main(String[] args) throws InterruptedException {
    System.out.println("先演示降级是可以的");
    Thread thread1 = new Thread(() -> writeDowngrading(), "Thread1");
    thread1.start();

}

读锁升级为写锁

private static void readUpgrading() {
    readLock.lock();
    try {
        System.out.println(Thread.currentThread().getName() + "得到了读锁,正在读取");
        Thread.sleep(1000);
        System.out.println("升级会带来阻塞");
        writeLock.lock();
        System.out.println(Thread.currentThread().getName() + "获取到了写锁,升级成功");
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        System.out.println(Thread.currentThread().getName() + "释放读锁");
        readLock.unlock();
    }
}

public static void main(String[] args) throws InterruptedException {
    System.out.println("演示升级是不行的");
    Thread thread2 = new Thread(() -> readUpgrading(), "Thread2");
    thread2.start();
}

⑥自旋锁和阻塞锁

private final AtomicReference<Thread> sign = new AtomicReference<>();

public void lock() {
    Thread current = Thread.currentThread();
    while (!sign.compareAndSet(null, current)) {
        System.out.println("自旋获取失败,再次尝试");
    }
}

public void unlock() {
    Thread current = Thread.currentThread();
    sign.compareAndSet(current, null);
}

public static void main(String[] args) {
    SpinLock spinLock = new SpinLock();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "开始尝试获取自旋锁");
            spinLock.lock();
            System.out.println(Thread.currentThread().getName() + "获取到了自旋锁");
            try { 
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                spinLock.unlock();
                System.out.println(Thread.currentThread().getName() + "释放了自旋锁");
            }
        }
    };
    Thread thread1 = new Thread(runnable);
    Thread thread2 = new Thread(runnable);
    thread1.start();
    thread2.start();
}

⑥可中断锁

private Lock lock = new ReentrantLock();
public static void main(String[] args) {
    LockInterruptibly lockInterruptibly = new LockInterruptibly();
    Thread thread0 = new Thread(lockInterruptibly);
    Thread thread1 = new Thread(lockInterruptibly);
    thread0.start();
    thread1.start();

    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    thread1.interrupt();
}
@Override
public void run() {
    System.out.println(Thread.currentThread().getName() + "尝试获取锁");
    try {
        lock.lockInterruptibly();
        try {
            System.out.println(Thread.currentThread().getName() + "获取到了锁");
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            System.out.println(Thread.currentThread().getName() + "睡眠期间被中断了");
        } finally {
            lock.unlock();
            System.out.println(Thread.currentThread().getName() + "释放了锁");
        }
    } catch (InterruptedException e) {
        System.out.println(Thread.currentThread().getName() + "获得锁期间被中断了");
    }
}

四·atomic

①介绍

②AtomicInteger

演示原子类与非原子类

private static final AtomicInteger atomicInteger = new AtomicInteger();

public void incrementAtomic() {
    atomicInteger.getAndIncrement();
}

private static volatile int basicCount = 0;

public void incrementBasic() {
    basicCount++;
}

public static void main(String[] args) throws InterruptedException {
    AtomicIntegerDemo1 r = new AtomicIntegerDemo1();
    Thread t1 = new Thread(r);
    Thread t2 = new Thread(r);
    t1.start();
    t2.start();
    t1.join();
    t2.join();
    System.out.println("原子类的结果:" + atomicInteger.get());
    System.out.println("普通变量的结果:" + basicCount);
}

@Override
public void run() {
    for (int i = 0; i < 100000; i++) {
        incrementAtomic();
        incrementBasic();
    }
}

在非原子方法上加锁也可变成线程安全的

③AtomicArray

public class AtomicArrayDemo {
    public static void main(String[] args) throws InterruptedException {
        AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(1000);
        Incrementer incrementer = new Incrementer(atomicIntegerArray);
        Decrementer decrementer = new Decrementer(atomicIntegerArray);
        Thread[] threadsIncrementer = new Thread[100];
        Thread[] threadsDecrementer = new Thread[100];
        for (int i = 0; i < 100; i++) {
            threadsDecrementer[i] = new Thread(decrementer);
            threadsIncrementer[i] = new Thread(incrementer);
            threadsDecrementer[i].start();
            threadsIncrementer[i].start();
        }

//        Thread.sleep(10000);
        for (int i = 0; i < 100; i++) {
            try {
                threadsDecrementer[i].join();
                threadsIncrementer[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        for (int i = 0; i < atomicIntegerArray.length(); i++) {
            if (atomicIntegerArray.get(i)!=0) {
                System.out.println("发现了错误"+i);
            }
            System.out.println(atomicIntegerArray.get(i));
        }
        System.out.println("运行结束");
    }
}

class Decrementer implements Runnable {

    private AtomicIntegerArray array;

    public Decrementer(AtomicIntegerArray array) {
        this.array = array;
    }

    @Override
    public void run() {
        for (int i = 0; i < array.length(); i++) {
            array.getAndDecrement(i);
        }
    }
}

class Incrementer implements Runnable {

    private AtomicIntegerArray array;

    public Incrementer(AtomicIntegerArray array) {
        this.array = array;
    }

    @Override
    public void run() {
        for (int i = 0; i < array.length(); i++) {
            array.getAndIncrement(i);
        }
    }
}

④Atomic*Reference

public class SpinLock {

    private final AtomicReference<Thread> sign = new AtomicReference<>();

    public void lock() {
        Thread current = Thread.currentThread();
        while (!sign.compareAndSet(null, current)) {
            System.out.println("自旋获取失败,再次尝试");
        }
    }

    public void unlock() {
        Thread current = Thread.currentThread();
        sign.compareAndSet(current, null);
    }

    public static void main(String[] args) {
        SpinLock spinLock = new SpinLock();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "开始尝试获取自旋锁");
                spinLock.lock();
                System.out.println(Thread.currentThread().getName() + "获取到了自旋锁");
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    spinLock.unlock();
                    System.out.println(Thread.currentThread().getName() + "释放了自旋锁");
                }
            }
        };
        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);
        thread1.start();
        thread2.start();
    }
}

⑤普通变量升级为原子功能变量

public class AtomicIntegerFieldUpdaterDemo implements Runnable{

    static Candidate tom;
    static Candidate peter;

    public static AtomicIntegerFieldUpdater<Candidate> scoreUpdater = AtomicIntegerFieldUpdater
            .newUpdater(Candidate.class, "score");

    @Override
    public void run() {
        for (int i = 0; i < 100000; i++) {
            peter.score++;
            scoreUpdater.getAndIncrement(tom);
        }
    }

    public static class Candidate {

        volatile int score;
    }

    public static void main(String[] args) throws InterruptedException {
        tom=new Candidate();
        peter=new Candidate();
        AtomicIntegerFieldUpdaterDemo r = new AtomicIntegerFieldUpdaterDemo();
        Thread t1 = new Thread(r);
        Thread t2 = new Thread(r);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("普通变量:"+peter.score);
        System.out.println("升级后的结果"+ tom.score);
    }
}

⑥累加器

比较

AtomicLong

public class AtomicLongDemo {

    public static void main(String[] args) throws InterruptedException {
        AtomicLong counter = new AtomicLong(0);
        ExecutorService service = Executors.newFixedThreadPool(20);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            service.submit(new Task(counter));
        }
        service.shutdown();
        while (!service.isTerminated()) {

        }
        long end = System.currentTimeMillis();
        System.out.println(counter.get());
        System.out.println("AtomicLong耗时:" + (end - start));
    }

    private static class Task implements Runnable {

        private  AtomicLong counter;

        public Task(AtomicLong counter) {
            this.counter = counter;
        }

        @Override
        public void run() {
            for (int i = 0; i < 10000; i++) {
                counter.incrementAndGet();
            }
        }
    }
}

LongAdder

public class LongAdderDemo {

    public static void main(String[] args) throws InterruptedException {
        LongAdder counter = new LongAdder();
        ExecutorService service = Executors.newFixedThreadPool(20);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            service.submit(new Task(counter));
        }
        service.shutdown();
        while (!service.isTerminated()) {

        }
        long end = System.currentTimeMillis();
        System.out.println(counter.sum());
        System.out.println("LongAdder耗时:" + (end - start));
    }

    private static class Task implements Runnable {

        private LongAdder counter;

        public Task(LongAdder counter) {
            this.counter = counter;
        }

        @Override
        public void run() {
            for (int i = 0; i < 10000; i++) {
                counter.increment();
            }
        }
    }
}

五·CAS

①简介及原理


 

public class TwoThreadsCompetition implements Runnable {

    private volatile int value;

    public synchronized int compareAndSwap(int expectedValue, int newValue) {
        int oldValue = value;
        if (oldValue == expectedValue) {
            value = newValue;
        }
        return oldValue;
    }

    public static void main(String[] args) throws InterruptedException {
        TwoThreadsCompetition r = new TwoThreadsCompetition();
        r.value = 0;
        Thread t1 = new Thread(r,"Thread 1");
        Thread t2 = new Thread(r,"Thread 2");
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(r.value);
    }

    @Override
    public void run() {
        compareAndSwap(0, 1);
    }
}

②缺点

Java解决ABA问题AtomicStampedReference

一个初始值及一个时间戳

CAS

.

不仅会比较值的相等还会比较设置值的时间戳是否相等。
mysql实现乐观锁时也会新增一个版本号来解决ABA的问题。

六·final

①不变性

②作用

     

    

   

③栈封闭技术

public class StackConfinement implements Runnable {

    int index = 0;

    public void inThread() {
        int neverGoOut = 0;
        synchronized (this) {
            for (int i = 0; i < 10000; i++) {
                neverGoOut++;
            }
        }

        System.out.println(Thread.currentThread().getName()+":栈内保护的数字是线程安全的:" + neverGoOut);
    }

    @Override
    public void run() {
        for (int i = 0; i < 20000000; i++) {
            index++;
        }
        inThread();
    }

    public static void main(String[] args) throws InterruptedException {
        StackConfinement r1 = new StackConfinement();
        Thread thread1 = new Thread(r1,"t1");
        Thread thread2 = new Thread(r1,"t2");
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println("共享变量的数字是现成不安全的:"+r1.index);
    }
}
public class StackConfinement implements Runnable {

    int index = 0;

    public void inThread() {
        int neverGoOut = 0;
        synchronized (this) {
            for (int i = 0; i < 10000; i++) {
                neverGoOut++;
            }
        }

        System.out.println(Thread.currentThread().getName()+":栈内保护的数字是线程安全的:" + neverGoOut);
    }

    @Override
    public void run() {
        for (int i = 0; i < 20000000; i++) {
            index++;
        }
        inThread();
    }

    public static void main(String[] args) throws InterruptedException {
        StackConfinement r1 = new StackConfinement();
        Thread thread1 = new Thread(r1,"t1");
        Thread thread2 = new Thread(r1,"t2");
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println("共享变量的数字是现成不安全的:"+r1.index);
    }
}

七·并发集合

①并发容器概览

②集合历史

1、Vectory线程安全的List但是并发时效率不行

Synchornized关键字修饰在方法上

2、Hashtable线程安全的Map但是并发时效率不行

同样Synchornized关键字修饰在方法上

3、ArrayList线程不安全的

但是可以通过Collections.synchornizedList(new ArrayList<E>())变为线程安全的

public class SynList implements Runnable{
    static List <Integer> unSafe = new ArrayList<>();
    static List<Integer> safeList = Collections.synchronizedList(new ArrayList<>());

    @Override
    public void run() {
        for (int i = 0; i < 200000; i++) {
            unSafe.add(i);
            safeList.add(i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new SynList());
        Thread thread2 = new Thread(new SynList());
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println("现成安全的List:"+safeList.size());
        System.out.println("现成不安全的List:"+unSafe.size());
    }
}

源码追踪:

ArrayList继承了RandomAccess

锁住的是代码块,所以是线程安全的,但是效率也不比Vector好到哪里去

4、HashMap线程不安全的

但是可以通过Collections.synchornizedMap(new HashMap<>())实现线程安全

public class SynMap implements Runnable{
    static Map<String, Integer> unSafe = new HashMap<>();
    static Map<String, Integer> safeMap = Collections.synchronizedMap(new HashMap<>());


    @Override
    public void run() {
        for (int i = 0; i < 200000; i++) {
           unSafe.put(i+"",i);
            safeMap.put(i+"",i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new SynMap());
        Thread thread2 = new Thread(new SynMap());
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println("现成安全的Map:"+safeMap.size());
        System.out.println("现成不安全的Map:"+unSafe.size());

    }

源码追踪:

同样锁住的是代码块,所以是现成安全的,但是效率也不比HashTabel好到哪里去

CopyOnWriteArrayList使用读多写少的场景,在修改频繁的场景下效率没有Collections.synchornizedList(new ArrayList())效率高。

③Map

1、jdk1.7 hashMap死循环造成CPU100%

在多个线程同时扩容的时候会造成链表的死循环

https://coolshell.cn/articles/9606.html

2、hashMap 1.7和1.8结构图和特点

Jdk1.7拉链法

Jdk1.8拉链法升级为红黑树

当拉链法到达一定阈值时升级为红黑树

左边的值会比父节点小,右边的值会比父节点大

3、ConcurrentHashMap

JDK1.7

JDK1.8

1.7到1.8的升级

数据结构:
1.7采用一个一个的segment分段来实现具有并发能力但是只有16,1.8采用链表+红黑树,每个node都是独立的支持更高的并发。

Hash碰撞:

    1.7采用拉链法,1.8先采用拉链后面达到阈值时转为红黑树提高了查找效率

保证并发安全:

    1.7采用分段锁采用segment(集成了rentrantlock),1.8采用cas+synchornized实现

查询复杂度:

    1.7采用链表查询复杂度是O(n),1.8采用红黑树查询复杂度是O(logn)

 

为什么要在链表长度为8的时候转为红黑树:

   默认不是红黑树节点默认是链表节点,因为链表节点占的内存更少

   想要达到冲突为8,正常情况下为千万分之一的概率

④CopyOnWriteArrayList

ArryList使用迭代器修改、新增、删除数据再第二次进入循环执行iterator.next会报错

public class CopyOnWriteArrayListDemo1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        list.add("5");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            System.out.println(next);
            System.out.println("list is" + list);
            if (next.equals("1")) {
                list.add("6");
            }
            if (next.equals("2")) {
                list.remove("5");
            }
            if (next.equals("3")) {
                list.add("3 found");
            }
        }
        System.out.println(list);
    }
}

使用CopyOnWriteArryList迭代修改不会报错,但是本次迭代器获取数据不会是最新改变的list中的数据,即iterator.next()还是获取的是之前的数据

public class CopyOnWriteArrayListDemo1 {
    public static void main(String[] args) {
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        list.add("5");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            System.out.println(next);
            System.out.println("list is" + list);
            if (next.equals("1")) {
                list.add("6");
            }
            if (next.equals("2")) {
                list.remove("5");
            }
            if (next.equals("3")) {
                list.add("3 found");
            }
        }
        System.out.println("最终的list:"+list);
    }
}

⑤并发队列

1、阻塞队列

2、非阻塞队列

八·并发流程

countDownLatch

一等多

**
 * 描述:     工厂中,质检,5个工人检查,所有人都认为通过,才通过
 */
public class CountDownLatchDemo1 {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(5);
        ExecutorService service = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 5; i++) {
            final int no = i + 1;
            Runnable runnable = () -> {
                try {
                    //模拟工作时长
                    long l = (long) (Math.random() * 10000);
                    Thread.sleep(l);
                    System.out.println("No." + no + "完成了检查。用时:"+l+"ms");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    latch.countDown();
                }
            };
            service.execute(runnable);
        }
        System.out.println("等待5个人检查完.....");
        latch.await();
        System.out.println("所有人都完成了工作,进入下一个环节。");
        service.shutdown();
    }
}

多等一

/**
 * 描述:     模拟压测试时需要等到所有线程准备完毕再瞬时请求
 */
public class CountDownLatchDemo2 {
    public static void main(String[] args) {
        CountDownLatch begin = new CountDownLatch(1);
        ExecutorService service = Executors.newFixedThreadPool(5);
        AtomicInteger atomicInteger = new AtomicInteger();
        ArrayList<Runnable> runnables = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            final int no = i + 1;
            Runnable runnable = () -> {
                try {
                    long l = (long) (Math.random() * 10000);
                    Thread.sleep(l);
                    System.out.println("Thread." + no + "准备完毕,等待压测。准备时长:"+l+"ms");
                    atomicInteger.getAndIncrement();
                    begin.await();
                    System.out.println("Thread." + no + "开始压测");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
            runnables.add(runnable);
        }
        runnables.forEach(service::submit);
        //模拟检查线程是否准备完毕,准备发送请求
        while (atomicInteger.get()<runnables.size()){
//            System.out.println(atomicInteger.get());
        }
        System.out.println("总线程数为:"+runnables.size()+",执行标记位为:"+atomicInteger.get()+"线程准备完毕,开始压测!");
        begin.countDown();
        service.shutdown();
    }
}

一等多、多等一协同

*
 * 描述:     一等多、多等一协同
 */
public class CountDownLatchDemo1And2 {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch begin = new CountDownLatch(1);
        CountDownLatch end = new CountDownLatch(5);
        ExecutorService service = Executors.newFixedThreadPool(5);
        AtomicInteger atomicInteger = new AtomicInteger();
        ArrayList<Runnable> runnables = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            final int no = i + 1;
            Runnable runnable = () -> {
                try {
                    //模拟准备时间
                    long l = (long) (Math.random() * 10000);
                    Thread.sleep(l);
                    System.out.println("Thread." + no + "准备完毕,等待压测,准备时间:"+l+"ms");
                    atomicInteger.getAndIncrement();
                    begin.await();
                    System.out.println("Thread." + no + "开始压测");
                    //模拟请求时间
                    long l2 = (long) (Math.random() * 10000);
                    Thread.sleep(l2);
                    System.out.println("Thread." + no + "压测完毕,执行时间:"+l2+"ms");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    end.countDown();
                }
            };
            runnables.add(runnable);
        }
        runnables.forEach(service::submit);
        //模拟检查线程是否准备完毕,准备发送请求
        while (atomicInteger.get()<5){

        }
        System.out.println("执行标记位为:"+atomicInteger.get()+"线程准备完毕,开始压测!");
        begin.countDown();
        end.await();
        System.out.println("所有线程均请求完毕,压测结束");
        service.shutdown();
    }
}

semaphore

基操

public class SemaphoreDemo {
    static Semaphore semaphore = new Semaphore(3, true);
    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(50);
        for (int i = 0; i < 12; i++) {
            service.submit(new Task());
        }
        service.shutdown();
    }
    static class Task implements Runnable {
        @Override
        public void run() {
            try {
                semaphore.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "拿到了许可证");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "释放了许可证");
            semaphore.release();
        }
    }
}

③condition

public class ConditionDemo1 {
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    void method1() throws InterruptedException {
        lock.lock();
        try{
            System.out.println("条件不满足,开始await");
            condition.await();
            System.out.println("条件满足了,开始执行后续的任务");
        }finally {
            lock.unlock();
        }
    }

    void method2() {
        lock.lock();
        try{
            System.out.println("准备工作完成,唤醒其他的线程");
            condition.signal();
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ConditionDemo1 conditionDemo1 = new ConditionDemo1();
        new Thread(() -> {
            try {
                Thread.sleep(1000);
                conditionDemo1.method2();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        new Thread(() -> {
            try {
                Thread.sleep(1000);
                conditionDemo1.method1();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

生产者消费者模式

public class ConditionDemo2 {
    private int queueSize = 10;
    private PriorityQueue<Integer> queue = new PriorityQueue<Integer>(queueSize);
    private Lock lock = new ReentrantLock();
    private Condition notFull = lock.newCondition();
    private Condition notEmpty = lock.newCondition();

    public static void main(String[] args) {
        ConditionDemo2 conditionDemo2 = new ConditionDemo2();
        Producer producer = conditionDemo2.new Producer();
        Consumer consumer = conditionDemo2.new Consumer();
        producer.start();
        consumer.start();
    }

    class Consumer extends Thread {

        @Override
        public void run() {
            consume();
        }

        private void consume() {
            while (true) {
                lock.lock();
                try {
                    while (queue.size() == 0) {
                        System.out.println("队列空,等待数据");
                        try {
                            notEmpty.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    queue.poll();
                    notFull.signalAll();
                    System.out.println("从队列里取走了一个数据,队列剩余" + queue.size() + "个元素");
                } finally {
                    lock.unlock();
                }
            }
        }
    }

    class Producer extends Thread {

        @Override
        public void run() {
            produce();
        }

        private void produce() {
            while (true) {
                lock.lock();
                try {
                    while (queue.size() == queueSize) {
                        System.out.println("队列满,等待有空余");
                        try {
                            notFull.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    queue.offer(1);
                    notEmpty.signalAll();
                    System.out.println("向队列插入了一个元素,队列剩余空间" + (queueSize - queue.size()));
                } finally {
                    lock.unlock();
                }
            }
        }
    }
}

④CyclicBarrier

public class CyclicBarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() {
            @Override
            public void run() {
                System.out.println("所有人都到场了, 大家统一出发!");
            }
        });
        for (int i = 0; i < 10; i++) {
            new Thread(new Task(i, cyclicBarrier)).start();
        }
    }

    static class Task implements Runnable{
        private int id;
        private CyclicBarrier cyclicBarrier;

        public Task(int id, CyclicBarrier cyclicBarrier) {
            this.id = id;
            this.cyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {
            System.out.println("线程" + id + "现在前往集合地点");
            try {
                Thread.sleep((long) (Math.random()*10000));
                System.out.println("线程"+id+"到了集合地点,开始等待其他人到达");
                cyclicBarrier.await();
                System.out.println("线程"+id+"出发了");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}

九·AQS

①简介

②用法及源码

share的是共享锁,不带的是独占锁

1、CountDownLatch

构造方法

await()

countDown()

2、Semaphore

构造方法

公平:

不公平:

aquire()

公平锁实现:

非公平锁实现:

释放许可证的方法release()

3、ReentrantLock

lock()

非公平锁的实现:

公平锁的实现:

unlock()

释放方法公平与非公平锁都是用的Sync里面方法

十·Future

 

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值