【持续更新】JUC并发编程

本文深入探讨了Java并发编程中的Synchronized与Lock的区别,包括自动释放、可检查性、可重入性等方面。同时介绍了并发辅助类如CountDownLatch、CyclicBarrier和Semaphore,以及阻塞队列BlockingQueue的使用。还涵盖了线程池的三种创建方式及四种拒绝策略,以及四大函数式接口的应用。最后,文章讨论了Volatile特性和单例模式的实现方式。
摘要由CSDN通过智能技术生成

Synchronized和Lock锁的区别

1.Synchronized是内置的java关键字,Lock是java的一个类
2.Synchronized锁是自动释放的,Lock锁则需要手动解锁
3.Lock可以检查是否有锁,java.lang.Thread下的holdslock()方法,Synchronized不能
4.Synchronized可重入锁,不可以中断,非公平,Lock可重入锁,非公平(但可以更改)
5.Synchronized线程1(获得锁,阻塞),线程2(一直等),Lock不会一直等,会尝试获得锁trylock()
6.Synchronized适合锁少量代码同步问题,Lock适合锁大量同步代码

八锁问题

非静态方法的锁默认为this,静态方法的锁为对应的class实例(这里是Number.class)
某一个时刻内,只能有一个线程持有锁,无论有几个方法。

总结:

①一个对象里面如果有多个synchronized方法,某一个时刻内,只要一个线程去调用其中的一个synchronized方法了,其他的线程都只能等待,换句话说,某一时刻内,只能有唯一一个线程去访问这些synchronized方法。

②锁的是当前对象this,被锁定后,其他线程都不能进入到当前对象的其他的synchronized方法。

③加个普通方法后发现和同步锁无关。

④换成静态同步方法后,情况又变化

⑤所有的非静态同步方法用的都是同一把锁 – 实例对象本身,也就是说如果一个实例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁,可是别的实例对象的非静态同步方法因为跟该实例对象的非静态同步方法用的是不同的锁,所以毋须等待该实例对象已经取锁的非静态同步方法释放锁就可以获取他们自己的锁。

⑥所有的静态同步方法用的也是同一把锁 – 类对象本身,这两把锁是两个不同的对象,所以静态同步方法与非静态同步方法之间不会有竞争条件。但是一旦一个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁,而不管是同一个实例对象的静态同步方法之间,还是不同的实例对象的静态同步方法之间,只要它们是同一个实例对象

Condition实现精准唤醒

可以在代码中加多个condition实现指定唤醒
condition.await() 使condition等待
condition.signal() 唤醒condition

常用辅助类

1.CountDownLatch(减法计数器)
await() 等待计数器完成
2.CyclicBarrier(加法计数器)
await() 等待计数器完成
3.Semaphore(信号量)
acquire() 得到
release() 释放

阻塞队列BlockingQueue的API

1.抛出异常
添加:add()
移除:remove()
检测队首元素:element()

2.不抛出异常,有返回值
添加:offer()
移除:poll()
检测队首元素:peek()

3.阻塞 等待
添加:put()
移除:take()

4.超时 等待
添加:offer(, ,)
移除:poll(,)

线程池

三个方法

Executors.newSingleThreadExecutor()  //单个线程
Executors.newFixedThreadPool(int nThreads)     //创建一个固定的线程池的大小
Executors.newCachedThreadPool()      //缓存池,可伸缩的, 遇强则强,遇弱则弱

七个参数

public ThreadPoolExecutor(int corePoolSize,                     //核心线程池大小           
                          int maximumPoolSize,                  //最大核心线程池大小
                          long keepAliveTime,                   //超时了没有人调用就会释放
                          TimeUnit unit,                        //超时单位
                          BlockingQueue<Runnable> workQueue,    //阻塞队列
                          ThreadFactory threadFactory,          //线程工厂,创建线程的,一般不用动
                          RejectedExecutionHandler handler)     //拒绝策略

四个拒绝策略

  • new ThreadPoolExecutor.AbortPolicy() //银行满了,还有人进来,不处理这个人的,抛出异常
  • new ThreadPoolExecutor.CallerRunsPolicy() //哪来的去哪里!
  • new ThreadPoolExecutor.DiscardPolicy() //队列满了,丢掉任务,不会抛出异常!
  • new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试和最早的竞争,也不会抛出异常

四大函数式接口

函数型接口:
Function<T, R>
传入一个参数T,返回R
在这里插入图片描述

public static void main(String[] args) {
    Function function = new Function<String, String>() {
        @Override
        public String apply(String s) {
            return s;
        }
    };

    // 只要是函数式接口,就可以使用lambda表达式简化
    Function function1 = a -> {
        return a;
    };

    System.out.println(function.apply("WWWW") + "====" + function1.apply("XXXX"));
}

断定型接口:
Predicate
传入一个参数,返回一个布尔值
在这里插入图片描述

public static void main(String[] args) {
    // 传入一个参数,返回一个boolean值
    Predicate predicate = new Predicate<String>() {
        @Override
        public boolean test(String s) {
            return false;
        }
    };

    // 只要是函数式接口,就可以使用lambda表达式简化
    Predicate predicate1 = a -> {
        return false;
    };

    System.out.println(predicate.test("a") + "====" + predicate1.test("b"));
}

消费型接口:
Consumer
传入一个参数,没有返回值
在这里插入图片描述

public static void main(String[] args) {
    Consumer consumer = new Consumer<String>() {
        @Override
        public void accept(String s) {
            System.out.println(s);
        }
    };

    // 只要是函数式接口,就可以使用lambda表达式简化
    Consumer consumer1 = a -> {
        System.out.println(a);
    };

    consumer.accept("s");
    consumer1.accept("a");
}

供给型接口:
Supplier
不传入参数,返回一个值
在这里插入图片描述

 public static void main(String[] args) {
    Supplier supplier = new Supplier() {
        @Override
        public String get() {
            return "aaa";
        }
    };

    // 只要是函数式接口,就可以使用lambda表达式简化
    Supplier supplier1 = () -> {
        return "bbb";
    };

    supplier.get();
    supplier1.get();
}

谈谈对Volatile的理解

1.保证了可见性
2.不保证原子性
3.防止指令重排序

单例模式

(详见收藏夹)
1.饿汉式单例
2.DCL懒汉式单例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值