JUC

/ java / 2 条评论 / 1404浏览

java.util.concurretn(高并发)

乐观锁和悲观锁

Volatile

/**
 * volatile防止指令重排
 * synchronized:保证原子性
 */
class Singleton{
    public static volatile Singleton singleton = null;

    public static Singleton getSingleton(){
        //双端检锁机制
        if(singleton == null){
            synchronized (Singleton.class){
                if(singleton == null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

CAS(比较并交换)

Synchronized

线程六种状态

公平锁和非公平锁

可重入锁(递归锁)

自旋锁

    public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
        return var5;
    }

独占锁(写)/共享锁(读)/互斥锁(读写)

JUC下的几个常用类

CountDownLatch

        CountDownLatch countDownLatch = new CountDownLatch(6);//阻塞
        for (int i = 1; i <= 6; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "\t" + "国,灭亡");
                countDownLatch.countDown();//自减
            }, String.valueOf(i)).start();
        }
        countDownLatch.await();//唤醒
        System.out.println("秦统一");

CyclicBarrier

        CyclicBarrier cyclicBarrier = new CyclicBarrier(7, ()->{ System.out.println("召唤神龙!"); });

        for (int i = 0; i < 7; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "---龙珠");
                try {cyclicBarrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}
            }, String.valueOf(i)).start();
        }

Semaphore

        Semaphore semaphore = new Semaphore(3);//3个车位
        for (int i = 0; i < 6; i++) {//六辆车
            new Thread(() -> {
                try {
                    semaphore.acquire();//锁定资源
                    System.out.println(Thread.currentThread().getName() + "抢到车位!");
                    try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}
                    System.out.println(Thread.currentThread().getName() + "停车3秒后 还回车位!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    semaphore.release();//还回资源
                }
            }, String.valueOf(i)).start();
        }

阻塞队列 (BlockingQueue)

ArrayBlockingQueue

LinkedBlockingQueue

SynchroousQueue

        BlockingQueue<String> blockingQuery = new SynchronousQueue<>();
        new Thread(() -> {
            try {
                blockingQuery.put("aaa");
                System.out.println("put aaa success");
                blockingQuery.put("bbb");
                System.out.println("put bbb success");
                blockingQuery.put("ccc");
                System.out.println("put bbb success");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"rng").start();

        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + "取出:" + blockingQuery.take());
                TimeUnit.SECONDS.sleep(5);
                System.out.println(Thread.currentThread().getName() + "取出:" + blockingQuery.take());
                TimeUnit.SECONDS.sleep(5);
                System.out.println(Thread.currentThread().getName() + "取出:" + blockingQuery.take());
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"ig").start();

线程代码编写口诀

阻塞队列one

class Kitchen0{
    private Integer food = 0;

    public synchronized void increase() {
        try {
            while (food != 0){
                this.wait();//线程等待
            }
            food ++;
            System.out.println(Thread.currentThread().getName() + "\t老版本生产了一个食物,当前:" + food);
            this.notifyAll();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public synchronized void dncrease(){
        try {
            while (food == 0){
                this.wait();//线程等待
            }
            food --;
            System.out.println(Thread.currentThread().getName() + "\t老版本消费了一个食物,当前:" + food);
            this.notifyAll();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}


public class zero {

    public static void main(String[] args) {
        Kitchen0 kitchen = new Kitchen0();
        new Thread(() -> {
            for (int i = 0; i <=5; i++) {
                kitchen.increase();
            }
        },"rng").start();

        new Thread(() -> {
            for (int i = 0; i <=5; i++) {
                kitchen.dncrease();
            }
        },"ig").start();
    }
}

阻塞队列two()

class Kitchen{
    private Integer food = 0;
    Lock lock = new ReentrantLock();//初始化锁
    Condition condition  = lock.newCondition();

    public void increase() {
        lock.lock();//上锁
        try {
            while (food != 0){
                condition.await();//线程等待
            }
            food ++;
            System.out.println(Thread.currentThread().getName() + "\t生产了一个食物,当前:" + food);
            condition.signalAll();//唤醒所有线程
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();//解锁
        }
    }

    public void dncrease(){
        lock.lock();
        try {
            while (food == 0){
                condition.await();//线程等待
            }
            food --;
            System.out.println(Thread.currentThread().getName() + "\t消费了一个食物,当前:" + food);
            condition.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}


public class one {

    public static void main(String[] args) {
        Kitchen kitchen = new Kitchen();
        new Thread(() -> {
            for (int i = 0; i <=5; i++) {
                kitchen.increase();
            }
        },"rng").start();

        new Thread(() -> {
            for (int i = 0; i <=5; i++) {
                kitchen.dncrease();
            }
        },"ig").start();
    }
}

阻塞队列three

/**
 * 3.0版本的阻塞队列
 * Volatile/CAS/AtomicInteger/AtomicReference/BlockingQueue
 * 实现MQ底层
 * @author langao_q
 * @create 2020-04-18 21:45
 */
class Source{
    private volatile boolean FLAG = true;
    private AtomicInteger atomicInteger = new AtomicInteger();//初始值为0

    private BlockingQueue<String> blockingQueue = null;
    public Source(BlockingQueue blockingQueue){
        System.out.println("传进来的BlockingQueue是:" + blockingQueue.getClass().getName());
        this.blockingQueue = blockingQueue;
    }

    //生产方法
    public void prod() throws InterruptedException {
        String data = null;
        while (FLAG){
            data = atomicInteger.incrementAndGet() + "";
            boolean rest = blockingQueue.offer(data, 2L, TimeUnit.SECONDS);//把生产的数据放入队列
            if(rest)
                System.out.println(Thread.currentThread().getName() + "\t生产了数据:" + data);
            else
                System.out.println(Thread.currentThread().getName() + "\t生产数据失败!:" + data);
            TimeUnit.SECONDS.sleep(1);
        }
        System.out.println(Thread.currentThread().getName() + "\t停止生产数据");
    }

    //消费方法
    public void consum() throws InterruptedException {
        String data = null;
        while (FLAG){
            data = blockingQueue.poll(2L, TimeUnit.SECONDS);//从队列中取出生产数据
            if(data == null || data.equalsIgnoreCase("")){
                FLAG = false;
                System.out.println(Thread.currentThread().getName() + "\t超时退出!");
                return;
            }
            System.out.println(Thread.currentThread().getName() + "\t消费了数据:" + data);
        }
    }

    //暂停方法
    public void stop(){
        FLAG = false;
        System.out.println("停止生产和消费数据!");
    }
}
public class three {
    public static void main(String[] args) throws InterruptedException {
        Source s = new Source(new ArrayBlockingQueue(10));
        new Thread(() -> {//生产线程
            try {s.prod();} catch (InterruptedException e) {e.printStackTrace();}
        },"rng").start();
        new Thread(() -> {//消费线程
            try {s.consum();} catch (InterruptedException e) {e.printStackTrace();}
        },"ig").start();

        TimeUnit.SECONDS.sleep(10);//main线程休息10s 让前面两个线程操作
        s.stop();//停止生产和消费
    }
}

Callable(第三种实现多线程方式)

class mythread implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        System.out.println(Thread.currentThread().getName() + "\t 开启一个单独的线程");
        TimeUnit.SECONDS.sleep(3);
        return 1024;
    }
}

public class CallableDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> futureTask = new FutureTask<>(new mythread());//1.构造线程
        new Thread(futureTask, "IG").start();//2.启动线程
        Integer value = futureTask.get();//3.获取返回值(尽量往后放)
        System.out.println("Callable实现多线程的返回值:" + value);
    }
}

线程池

ThreadPoolExecutor(第四种实现多线程)

        //jdk提供方式(不用):ExecutorService threadPool = Executors.newFixedThreadPool(5);
        ExecutorService threadPool = new ThreadPoolExecutor(2,
                                                            5,
                                                            5,
                                                            TimeUnit.SECONDS,
                                                            new LinkedBlockingDeque<>(3),
                                                            Executors.defaultThreadFactory(),
                                                            new ThreadPoolExecutor.AbortPolicy());
        try {
            for (int i = 0; i < 10; i++) {//开启十个线程去访问
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "\t SUCCESS!");
                });
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {//用完线程一定要关闭
            threadPool.shutdown();
        }

线程池七大参数

public ThreadPoolExecutor(int corePoolSize,//线程池钟常驻核心线程数
                              int maximumPoolSize,//线程池能够容纳同时执行的最大线程数(大于1)
                              long keepAliveTime,//多余线程存活时间
                              TimeUnit unit,//时间单位
                              BlockingQueue<Runnable> workQueue,//任务队列 被提交但尚未被执行的任务(注意:只有在阻塞队列满了之后才会开始创建多余线程)
                              ThreadFactory threadFactory,//线程工厂 创建新的线程(默认即可)
                              RejectedExecutionHandler handler)//拒绝策略,当线程队列满了且工作线程大于maximumPoolSize时如何拒绝

线程池底层工作原理

1.在创建线程池后,等待提交过来的任务请求
2.当调用execute()方法添加一个任务请求时,线程池会马上创建线程运行这个任务
2.1如果正在运行的线程数量小于corePoolSize,那么马上创建线程运行这个任务
2.2如果正在运行的线程数量大于或等于corePoolSize,那么将这个任务放入队列
2.3如果队列满了且正在运行的线程数量小于maximumPoolSize,那么会创建非核心线程运行这个任务
2.4如果队列满了且正在运行的线程数量大于或等于maximumPoolSize,那么线程池会启动饱和和拒绝策略
3.当一个线程完成任务时,它会从队列中取下一个任务来执行
4.当一个线程闲置超过keepAliveTime的时间,线程池会判断
4.1如果当前线程数大于corePoolSize,那么这个线程会被停掉
4.2线程池的所有任务完成后它最终会收缩到corePoolSize的大小

线程池的四大拒绝策略

线程池参数的合理配置

死锁

产生原因

class Deadloc implements Runnable{
    private String lockAa,lockBb;
    public Deadloc(String lockAa, String lockBb){
        this.lockAa = lockAa;
        this.lockBb = lockBb;
    }
    @Override
    public void run() {
        synchronized (lockAa){
            System.out.println(Thread.currentThread().getName() + "\t 拿到锁:"+lockAa);
            try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) { e.printStackTrace();}
            synchronized (lockBb){
                System.out.println(Thread.currentThread().getName() + "\t 拿到锁:"+lockBb);
            }
        }
    }
}
public class DeadlockDemo {
    public static void main(String[] args) {
        Deadloc deadloc = new Deadloc("lockAa", "lockBb");
        Deadloc deadloc1 = new Deadloc("lockBb", "lockAa");
        new Thread(deadloc, "ThreadAAA").start();
        new Thread(deadloc1, "ThreadBBB").start();
    }
}

如何解决

jps -l

jstack 进程编号

Synchronized和Lock的区别

ThreadLocal的了解,实现原理。

每个线程都保存一份threadlocalmap的引用,以ThreadLocal和 ThreadLocal对象声明的变量类型作为参数