线程池如何实现参数的动态修改?

  • 利用微服务的配置中心
  • 如果限制了配置中心的使用,也可以自己去扩展ThreadPoolExecutor,重写方法,监听线程池参数变化,来动态修改线程池参数。

单机线程池执行断电了应该怎么处理?

  • 对阻塞队列持久化;正在处理任务事务控制;断电之后正在处理任务的回滚,通过日志恢复该次操作;服务器重启后阻塞队列中的数据再加载。

线程池的线程数应该怎么配置?

  • 一般任务分为计算密集型、IO密集型、混合型。
    • 计算密集型:大部分都在用CPU跟内存,加密,逻辑操作业务处理等。
    • IO密集型:数据库链接,网络通讯传输等。
  • 不同类型线程池的参数配置
    • 计算密集型:一般配置CPU数 + 1,+1 是因为可能存在页缺失,线程数配置过多,可能会造成线程上下文频繁切换,Runtime.getRuntime().availableProcessors() 获取CPU数;
    • IO密集型:线程数适当大一点,机器的Cpu核心数*2。
    • 混合型:可以考虑根绝情况将它拆分成CPU密集型和IO密集型任务,如果执行时间相差不大,拆分可以提升吞吐量,反之没有必要。

并行跟并发有什么区别?

  • 并行是两个线程同时执行
  • 并发是依赖线程的切换

说说什么是进程和线程?

  • 进程是系统进行资源分配和调度的基本单位。
  • 线程是是进程执行任务的一个最小单位

说说线程有几种创建方式?

  • 继承Thread
  • 实现Runnable接口
  • 实现Callable接口

线程有哪些常用的调度方法?

  • 线程的等待与通知
    • Object类
      • wait()
        • 通过notify()或者 notifyAll()唤醒
      • wait(long timeout)
        • 没有唤醒的话,超过设定的时间也会自动唤醒
    • Thread类
      • join()
  • 线程休眠
    • sleep(long millis) 不会释放锁
  • 让出优先权
    • yield()
  • 线程中断
    • void interrupt() :中断线程

线程有那些状态,分别说明什么情况才会进入该状态

  • NEW(新建):线程被创建,还没有调用start()
  • RUNNABLE(运行):调用了Start方法,但还没有获取到CPU资源
  • BLOCKED(阻塞):表示线程阻塞于锁
  • WAITING(等待):调用一些方法可以使线程进入等待状态
  • TIME_WAITING(超时等待):等待指定的时间段,自动返回到运行状态
  • TERMINATED(终止):执行完毕或抛出异常

线程间有哪些通信方式?

  • volatile和synchronized关键字
  • 等待/通知机制
  • 管道输入/输出流
  • 使用Thread.join()
  • 使用ThreadLocal

ThreadLocal 内存泄露是怎么回事?

  • 因为ThreadLocal的可以使它本身的一个弱引用,所以很容易被垃圾回收机制给回收掉,导致ThreadLocalMap中key被回收value还在的情况,造成内存泄漏
  • 用完及时remove可以避免

父子线程怎么共享数据?

  • 使用InheritableThreadLocal类

线程死锁了解吗?该如何避免?

  • 多个线程互相争夺资源造成互相等待的现象
  • 产生死锁的条件
    • 互斥条件
    • 请求并持有条件
    • 不可剥夺条件
    • 环路等待条件

那死锁问题怎么排查呢?

  • jps -l 查找运行的进程
  • jstack -l 进程id 查看线程堆栈信息
  • JConsole 提供了检测死锁的功能

CountDownLatch(倒计数器)了解吗?

  • 可以让多个线程等待所有线程就绪后再执行

CyclicBarrier(同步屏障)了解吗?

  • 可以让线程等待多次

Semaphore(信号量)了解吗?

  • 固定数量的执行槽,多个资源互相争抢执行

Exchanger 了解吗?

  • 可以在线程之间互相传递信息

线程池提交execute和submit有什么区别?

  • execute 用于提交不需要返回值的任务
  • submit()方法用于提交需要返回值的任务