文章目录

  • 线程通讯
  • **线程的状态**
  • 进程之间的通信方式
  • 线程之间的通信方式
  • wait与sleep
  • synchronized 与lock
  • 线程池
  • 线程池优点
  • **线程池的创建方式**
  • 线程池的七大参数
  • 线程池的5种拒绝策略·


线程通讯

线程的状态

  • 新建
  • 就绪
  • 运行
  • 阻塞
  • 等待和超时等待
  • 中止

进程之间的通信方式

  • 管道:是一种半双工的通信方式:数据只能单向流动,而且只能在具有亲缘关系的进程之间通信。(进程的亲缘关系通常是指父子进程关系)
  • 命名管道:半双工的通信方式,允许无亲缘关系进程间的通信
  • 消息队列:消息队列是消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息多少,管道只能继承无格式字节流以及缓冲区大小受限等特点。
  • 共享存储:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建但多个进程都可以访问
  • 信号量:是一个计数器,可以用来控制多个进程对共享资源的访问,他常用来作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源因。主要作为进程间以及统一进层不同线程之间的同步手段。
  • 套接字Socket:套接口也是一种进程间通信机制,他可用于不同机器间的进程通信
  • 信号:是进程间通信机制唯一的异步通信机制。

线程之间的通信方式

  • 锁机制
  • 信号量机制:包括无名线程信号和命名线程信号
  • 信号机制

wait与sleep

wait和sleep都是让线程进入休眠状态
在执行的过程中都可以接收到终止线程执行的通知

wait方法 永久等待,所以必须先加锁
唤醒操作也需要加锁
wait和notify在配合使用时,一定要使用同一把锁
notify 唤醒线程 (多线程时,随机唤醒一个线程):

如何指定:LockSupport park()/unpark(线程)
park:让线程进行休眠
unpake:(线程名)

wait不传递参数时:进入waiting状态(其底层实现也是调用了wait(0)这个方法;
传递大于0的参数时,进入time_waiting状态
传0的时候,进入waiting状态

sleep和wait的区别

  • wait执行的时候会释放锁,sleep执行时不会释放
  • wait使用必须配合synchronized一起使用,而sleep不用
  • wait是Object的方法,而sleep是Thread的方法
  • 默认情况下wait进入waiting状态,而sleep会进入timed_waiting状态
  • 使用wait时可以主动的唤醒进程,而sleep不能

sleep(0)和wait(0)有什么区别

  • sleep表示过0毫秒之后继续执行,而wait表示一直休眠
  • sleep(0)表示重新触发一次CPU竞争,

为什么wait会释放锁,而sleep不会释放锁?

  • sleep必须传入一个最大等待时间,也就是说sleep是可控的(对于时间层面来讲),而wait不传递参数。从设计层面讲如果wait这个没有超时等待·时间的机制不释放锁的话,那么线程可能会一直阻塞,而sleep不存在这个问题

为什么wait是object的方法,而sleep是Thread的方法?

  • wait需要操作锁,而锁是属于‘对象级别(所有的锁都是放在对象头里面)。它不是线程级别。一个线程中可以拥有多把锁,为了灵活期间,所以将wait放在Object当中

synchronized 与lock

synchronized 与 lock的区别

  • synchronized是java关键字,在jvm层面时间加锁和解锁:Lock是一个接口,在代码层面实现加锁和解锁
  • synchronized可以用在代码块上,方法上。lock只能写在代码里
  • synchronized在代码执行完成或者出现异常时自动释放锁:Lock不会自动释放锁:需要在finally中显示释放锁
  • synchronized会导致线程拿不到锁一直等待:Lock可以设置获取锁失败的超时时间
  • synchronized无法知道是否获取锁成功:Lock可以通过trylock得知加锁是否成功
  • synchronized锁可重入,不可中断,非公平;lock锁可重入,可中断,可公平/不公平,并且可以细分读写锁以提高效率

线程池

线程池的两个重要参数
1,线程
2,工作队列

线程池优点

线程缺点

  • 线程创建他会开辟本地方法栈,虚拟机栈,程序计数器等线程私有的内存对象,同时销毁的时候需要销毁以上三个区域,因此频繁的创建和消耗比较消耗系统资源;
  • 在任务量特别大的时候,并不能友好的拒绝任务

线程池:使用池化技术来管理线程和使用线程的方式

线程池优点

  • 可以避免频繁的创建和消耗线程
  • 可以更好的管理线程的个数和资源的个数
  • 拥有更多的功能,比如线程池可以进行定时任务的执行·
  • 线程池可以更优化的拒绝不能处理的任务

线程池的创建方式

  • 创建固定个数的线程池
  • 创建带缓存的线程池(短期有大量任务时时候使用)
  • 创建执行定时任务的线程池
    scheduleAtFixedRate:以上次任务的开始时间作为下一次任务的开始时间的
    scheduleWithFixedDelay:以上次任务的结束时间作为下一次任务的开始时间的
  • 创建单线程执行定时任务的线程池
  • 创建单个线程的线程池
    经典面试题:意义何在?

1 可以避免频繁创建和消耗线程带来的性能开销;
2 有任务队列可以存储多余的任务;
3 当有大量的任务不能处理的时候可以有好的执行拒绝策略
4 可以更好的管理和分配任务

  • 根据当前的硬件的CPU生成对应个数的线程池,并且是异步执行。
  • 最原始方式创建ThreadPoolExecutor

前六种线程池可能存在问题
线程数量不可控 —>OOM
工作任务队列不可控 —>OOM

线程池的七大参数

  • 核心线程数(正式员工的数量)
  • 最大线程数(正式员工和临时工)
  • 存活时间(临时工生存时间)
  • 时间单位
  • 任务队列(一定要初始化大小)
  • 线程工厂(设置线程池)
  • 拒绝策略

线程池的5种拒绝策略·

  • 默认拒绝策略(不执行新任务,抛出异常)
  • 将新任务交给主线程执行
  • 丢弃当前任务(当前任务+新任务)
  • 丢弃老任务
  • 自定义拒绝策略

ThreadLocal
set :将线程存储到ThreadLocal中
get:从线程中取私有变量
remove:移除私有变量