多线程并发相关知识点


https://thinkwon.blog.youkuaiyun.com/article/details/104863992

1、wait/sleep的区别:

  1. 来自不同的类:
    wait => Object
    sleep => Thread
  2. 关于锁的释放:
    wait会释放锁,sleep不会释放锁
  3. 使用范围:
    wait必须在同步代码块中使用,而sleep可以在任何地方使用
  4. 是否需要捕获异常:
    wait不需要捕获异常,sleep需要捕获异常
  5. 同:都是让线程进入等待状态。

2、synchronized出现异常会释放锁?

会释放。

3、synchronized和Lock的区别?

  • synchronized是关键字,Lock是接口;
  • synchronized是不可中断的,Lock是可中断的,也可以是不可中断的;
  • synchronized会自动释放锁,Lock锁需要手动释放锁;
  • synchronized是非公平锁,Lock锁可以是公平锁也可以是非公平锁‘;
  • Lock可以知道线程有没有获取锁,而synchronized不能;
  • synchronized可以锁代码块和方法,Lock锁只能锁代码块;

4、Runnable和Callable的区别?

  1. Callable有返回值,而Runnable没有返回值
  2. Callable可以抛出异常,而Runnable不能抛出异常
  3. Callable的方法是call(),而Runnable的方法是run()

为什么Runnable接口的run方法不能抛出异常,而必须捕获呢?

因为Runnable接口中的run方法没有抛出异常,所以子类在重写run方法时,不能抛出异常。

5、为什么内部类不能访问非final的局部变量?

局部变量的生命周期:当该方法被调用时,该方法中的局部变量在栈中被创建,当方法调用结束时,退栈,这些局部变量全部死亡。而内部类对象生命周期与其它类对象一样:自创建一个匿名内部类对象,系统为该对象分配内存,直到没有引用变量指向分配给该对象的内存,它才有可能会死亡(被JVM垃圾回收)。所以完全可能出现的一种情况是:成员方法已调用结束,局部变量已死亡,但匿名内部类的对象仍然活着。

6、阻塞队列方法的区别?

在这里插入图片描述

阻塞队列的使用:

操作抛出异常有返回值(true/false)阻塞等待超时等待
添加add()offer()put()offer(E e, long timeout, TimeUnit unit)
移除remove()poll()take()poll(long timeout, TimeUnit unit)
获取队首元素element()peek()

当使用add()往一个满的队列中加入元素时,会抛出如下的异常:

抛出异常:

java.lang.IllegalStateException: Queue full

当使用remove()移除一个空队列的元素时,或者使用element()获取一个空队列的队首元素时,会抛出如下异常:

队列为空:

java.util.NoSuchElementException

使用offer()往队列添加元素,添加成功返回true,队满添加失败,返回false。

使用poll()出队元素时,或者peek()获取队首元素时,如果元素存在,则返回元素,否则返回null。


当使用put()往队列添加元素时,如果队列不满则添加成功,否则会阻塞(一直阻塞)。

当使用take()出队元素时,如果队列有元素则出队,并返回该元素,如果队列为空,调用该方法则会阻塞(一直阻塞)。


offer(E e, long timeout, TimeUnit unit) 可以指定超时等待的时间,不会一直等待下去。

poll(long timeout, TimeUnit unit) 也一样。


7、线程池详解

https://blog.youkuaiyun.com/Linging_24/article/details/109401629

8、自定义线程池时,我们如何确定线程池的最大线程数量?

  1. CPU密集型:

    CPU是几核的就是几,可以保持CPU的效率最高。

    Runtime.getRuntime().availableProcessors();	//获取CPU最大并行线程的数量。
    
  2. IO密集型:

    判断我们程序中非常耗IO的任务数量,比这个数大就可以,可以设置为2倍。

使用多线程时,主要是为了提高CPU的利用率。
我们的任务一般分为计算密集型和IO密集型。

计算密集型:主要是需要CPU的频繁计算,来产生结果的,所以任务越多,我们CPU的切换所需要消耗的资源就越多,所以一般保持和CPU核心数的任务或者+1这样就可以,每个任务就是一个线程,所以对于计算密集型任务来说,线程的最大数量就是CPU核心数量或者+1。

IO密集型:IO密集型任务的特点是CPU的使用率比较低,一般时间都浪费在网络连接或者磁盘操作等原因,所以任务越多CPU的利用率就越高,但是也有限度,一般设置为CPU核心数量的2倍即可。

9、volatile如何保证可见性和有序性?

https://blog.youkuaiyun.com/bfj11/article/details/123949405
https://blog.youkuaiyun.com/jyxmust/article/details/76946283

有序性:lock指令前缀 + 内存屏障
可见性:内存屏障

内存屏障的两个作用:

  1. 禁止指令重排序
  2. 读写强刷,立即可见

10、synchronized详解

https://blog.youkuaiyun.com/Linging_24/article/details/110541592

11、JUC三大辅助类

  • CountDownLatch:实现让一个线程等待其他线程执行完毕后再执行。
  • CyclicBarrier:实现让一组线程等待至某一状态,再全部同时执行。
  • Semaphore:Semaphore 是 synchronized 的加强版,作用是控制线程的并发数量。

12、线程的状态

在这里插入图片描述

  • 新建状态:
    使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。

  • 就绪状态:
    当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。

  • 运行状态:
    如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。

  • 阻塞状态:
    如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:

    • 等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
    • 同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
    • 其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
  • 死亡状态:
    一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。

13、产生死锁的四个必要条件:

(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

11、练习题

  1. 三个线程t1、t2、t3。确保三个线程,t1执行完后t2执行,t2执行完后t3执行。执行顺序:t1->t2->t3
1.Semaphore实现,初始凭证0
2.Lock + condition实现
3.synchronized + wait + notifyAll实现
4.join
  1. 三个线程t1、t2、t3。确保三个线程,t1,t2执行完,t3再执行
1.CountDownLatch实现
2.join实现
3.synchronized + wait + notifyAll实现
4.Lock + condition实现
  1. 生产者消费者问题
1.synchronized + wait + notifyAll实现
2.Lock + condition实现
  1. 多线程循环顺序打印:ABABABABAB,线程A打印A,线程B打印B。
1.synchronized + wait + notifyAll实现
2.Lock + condition实现
  1. 多线程循环顺序打印:0102030405,线程0打印0,线程1打印奇数,线程2打印偶数
1.synchronized + wait + notifyAll实现
2.Lock + condition实现

12、基于ReentrantLock详解AQS

https://blog.youkuaiyun.com/Linging_24/article/details/134961383

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值