java之juc详解

实现线程的几种方式

  • 继承Thread类
  • 实现Runnable接口
  • 实现Callable接口
  • 从线程池中获取

Runnable接口和Callable接口的主要区别在于:Runnable接口没有返回值,而Callable接口call方法有返回值。

线程的状态主要分为6种:初始、运行、阻塞、等待、超时等待、终止

start()方法和run()方法的主要区别在于start是启动一个线程,而run方法是开始执行线程里的方法。

死锁

什么是线程死锁?

死锁是指两个或者两个以上的线程在执行的过程中,由于相互竞争资源而造成的一种相互阻塞的情况。

造成死锁的四个必要条件?
  • 互斥条件
  • 请求与保持
  • 不剥夺条件
  • 循环等待
如何避免线程死锁?
  • 避免一个线程同时获得多个锁
  • 避免一个线程在锁内同时占有多个资源,尽量保证每个锁只占用一个资源
线程调度的相关方法?
  • wait():使一个线程处于阻塞状态,并释放锁
  • sleep():使一个线程处于睡眠状态,但是不会释放锁
  • notify():随机唤醒一个线程
  • notityAll():唤醒所有线程

Java内存模型(JMM)

Java内存模型(简称JMM)定义了线程和主内存之间的抽象关系:线程之间的共享变量储存在主内存中,每个线程都有一个私有的本地内存,在线程进行操作时,会先将共享内存中的值读取到本地内存进行修改之后在刷新回主内存。

java之juc详解_第1张图片

synchronized

多线程中 synchronized 锁升级的原理是什么?

synchronized 锁升级原理:在锁对象的对象头里面有一个 threadid 字段,在第一次访问的时候 threadid 为空,jvm 让其持有偏向锁,并将 threadid 设置为其线程 id,再次进入的时候会先判断 threadid 是否与其线程 id 一致,如果一致则可以直接使用此对象,如果不一致,则升级偏向锁为轻量级锁,通过自旋循环一定次数来获取锁,执行一定次数之后,如果还没有正常获取到要使用的对象,此时就会把锁从轻量级升级为重量级锁,此过程就构成了 synchronized 锁的升级。

volatile

volatile主要保证了可见性、有序性,但是不保证原子性,可以结合原子操作类atomic,保证原子操作。只能修饰一个变量

AQS

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XEMm8mu5-1613559473254)(C:\Users\j\AppData\Roaming\Typora\typora-user-images\image-20200525173659408.png)]

Aqs核心思想:利用cas操作,保证只有一个线程能够修改状态,获得锁,未获得锁的线程进入等待队列等待被唤醒。

private volatile int state;//共享变量,使用volatile修饰保证线程可见性

对state使用volatile修饰。

cas(比较并交换)

是一种乐观锁。采用自旋,通过不断比较工作空间和主内存中得值是否一样。

缺点:

  • ABA问题
  • 循环开销大
  • 只能保证一个共享变量得原子操作

并发工具类

countDownLatch:所有得线程都执行完才开始执行下一步

CyclicBarrier:所有得线程都到了某一个点,才开始放行线程。

Semaphore:信号量,类似于抢车位,有一个上限值,超过上限会被阻塞,执行完后会归还。

线程池

线程池的优点:1、降低资源的消耗。2、提高响应速度。3、提高线程的可管理型

常用的线程池4种:其核心类是ThreadPoolExcutor,,可以让我们自定义线程池,他又7大参数,第一个是线程池中的常驻核心线程数,第二个是线程池能够容纳的最大线程数,第三个是多余线程数的存活时间,第四个是存活时间的单位,第五个是任务队列,就是指阻塞队列。第六个是线程工厂,一般用默认的。第七个是拒绝策略。

阻塞队列的种类:由数组构成的阻塞队列、由链表构成的阻塞队列、

线程池的工作原理

(1) 当线程池刚创建的时候,会进入任务等待状态。

(2) 当调用execute()方法的时候,会添加一个任务,这是线程池会做出判断,

​ A、如果正在运行的线程数量小于核心线程数,就立即启动这个线程,

​ B、如果正在运行的线程数大于或者等于核心线程数,就会放入任务队列。

​ C、如果这个时候任务队列满了,而且运行的线程数量小于最大线程数量,就创建线程继续运行任务。

​ D、如果队列满了,并且正在运行的线程数量等于最大线程数量,此时就会抛出异常。

(3)当一个线程任务完成得时候,就会从任务队列中拿出一个任务执行。

(4)当一个线程执行完任务后,超过设定的最大等待时常,就会判断当前线程数是否大于核心线程数,如果大于就会停掉,当全部完成后,保持线程数量为核心线程数。

你可能感兴趣的