多线程的相关知识点(下)

多线程的相关知识点

12.死锁

死锁的四个条件:
互斥:
资源x在任意时刻只能被一个线程持有
占有且等待:
线程1占有资源x的同时等待资源y,并不释放x
不可抢占:
资源x一旦被线程1占有后,其他线程不能抢占资源x
循环等待:
线程1持有x,等待y;线程2持有y,等待x
死锁产生的原因:以上四个原因同时满足
synchronized如何来解决死锁?
以上四个条件都不能破坏,因此产生Lock。

13.JDK1.5 Lock体系【接口】

使用格式:搭配

try{
//同步代码块、显示加锁
Lock.lock();
}catch(Exception e){
}finally{
//显示解锁 
lock.unlock();
}

常用方法
线程停止三个方法:(1)stop()
(2)设置标记位
(3)interrupt()
lock():加锁,语义与synchronized完全一致
unlock():解锁
(1)void lockInterruptiblity()throw InterruptdException:响应中断加锁【不可抢占抛开】
(2)boolean tryLock():非阻塞获取锁,获取锁成功返回true,进入同步块;获取锁失败返回false,线程继续执行其他的代码。【占有且等待抛开】
(3)boolean tryLock(long time,TimeUnit unit)throw InterruptdException:支持超时【不可抢占、占有且等待抛开】

14.synchronized与ReentrantLock的关系与区别?

关系:
1.都属于独占锁(任意一个时刻只有一个线程能获取到资源)的实现
2.都支持可重入锁
区别:
(1)synchronized是关键字,JVM层面实现;
ReentrantLock是Java语言层面实现的“管程”。
(2)ReentrantLock具备一些synchronized不具备的功能:响应中断、非阻塞式中断、支持超时获取锁、支持公平锁、支持多个等待队列。
公平锁:等待时间最长的线程最先获取到锁。

15.线程的等待与唤醒机制(线程通信方法之一)

wait/notify:synchronized
调用notify后,将等待队列的线程唤醒置入同步队列末尾排队获取锁
notify线程直到将自己的同步块执行完毕后才会释放锁
任意一个Monitor有一个同步队列和一个等待队列(生产、消费都进入一个队列)
只有一个等待队列时,唤醒所有线程会造成不该唤醒的线程又被唤醒然后再次阻塞,造成性能开销。
notifyAll()->所有线程都唤醒(包含消费者)

await/signal:Lock
Condition:等待队列模型
任意一个Lock对象有一个同步队列和多个等待队列(Lock.condition())
Lock体系下另外一个子类:ReentrantReadWriteLock[可重入的读写锁]
独占锁:
任意一个时刻只有一个线程能获取到资源
共享锁:
任意一个时刻有多个线程可以获取锁
读写锁:
读锁:共享锁,读线程与读线程是异步,可以同时获取到锁
写锁:独占锁,写线程与写线程互斥,只有一个写者可以获取到锁
读写互斥、写写互斥
读锁==无锁?一定不等
写线程开始工作时,可以限制所有读线程阻塞
缓冲:Map
HashMap+ReentrantReadWriteLock=高效线程Map
JDK1.8 StampLock

16.juc 四大并发工具类

juc.CountDownLatch 闭锁
一个线程等待一组线程执行完毕后在恢复执行
await():等待其他线程都执行完毕
cutDown():被等待线程执行完毕后将计数器减一
当CountDownLatch值减为0时无法恢复[计数器无法恢复]
juc.CyclicBarrier:循环栅栏
一组线程同时到达临界点后同时恢复执行(先到达临界点的线程会阻塞,直到所有线程都到达临界点)
当多个线程同时到达临界点时,随机挑选一个线程执行barrierAction后再同时恢复执行
多线程向磁盘写入数据[计数器可以恢复]
juc.Exchanger:线程交换器
用于两个线程之间数据交换,当Exchanger只有一个线程时,该线程会阻塞直到有别的线程调用Exchanger进入缓存区,当前线程与新线程交换数据后同时恢复执行。
juc.Semaphore:信号量
acquire():尝试占用一个信号量,失败的线程会阻塞直到有新的信号量
release():释放一个占有的信号量
acquire(int n):尝试占用n个信号量,失败的线程会阻塞直到有新的信号量
release(int n):释放n个占有的信号量
TreadLocal:线程本地变量

17.线程池

为啥要采用线程池?
【优点】方便管理与监控线程的状态、提高任务响应速度、线程可以重复执行任务
数据库连接池Druid、C3p0、Hakari
数据源DataSource
ExecutorService:普通调度池接口
submit——(Runnable||Callable):Future
execute——(Runnable):void
子接口ScheduleExecutorService:定时调度池(可以执行定时任务)
TreadPoolExecutor:线程池核心实现类
Executors:线程池工具类
线程池的工作流程:当任务到达线程池时的工作顺序
核心线程池corePoolSize、阻塞队列BlockingQueue、最大线程池maxiumPoolSize、拒绝策略rejectHandler

(1)若核心池未满,则创建新的线程执行任务而后将此线程入核心池。若核心池满且有空闲线程,调度空闲线程执行任务。
(2)将任务置入阻塞队列,排队等待空闲线程调度
ArrayBlockQueue:基于数组的有界阻塞队列
LinkedBlockingQueue:基于链表的无界阻塞队列
SynchrousQueue:不存储元素的无界阻塞队列
(3)当阻塞队列满时,若此时最大线程池未满,创建新线程执行任务而后置入最大线程池中
(4)若最大线程池已满,调用相应的拒绝策略处理任务(默认为抛出异常且不处理任务)
手工创建线程池
Thread类执行Callable FutureTask
FutureTask类保证多线程场景下任务只被执行1次
Future get()会阻塞当前线程直到取得Callable的返回值

18.JDK内置的四大线程池(Exectors)

(1)固定大小线程池:LinkedBlockQueue[核心线程池与最大线程池数目相同]

  return new ThreadPoolExecutor(nThreads,nThreads,0L,TimeUnit.MILLISECONDS,
                                                          new LinkedBlockQueue<Runnable>());

应用场景:当服务器负载较重时,限制线程的数量,可以采用固定大小线程池
(2)单线程池:newSingleThreadExecutor
应用场景:某些需要同步处理的场合(任务需要按序处理)

 return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));

(3)缓存线程池:newCachedThreadPool
应用场景:适用于负载较轻的服务器,适用于很多短期的小任务

 return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());

(4)定时调度池:newScheduledThreadPool
应用场景:需要执行定时任务的场合

public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }

SynchronousQueue:不存储元素
入队与出队操作必须同时调用
提交任务速度>执行任务速度:不断创建新线程执行任务,有可能会将内存写满
提交任务速度<执行任务速度:固定的几个线程来处理任务
线程池:工作流程、ThreadPoolExecutor参数会配置(自定义线程)、内置四大线程池使用场景

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值