JavaEE——线程小知识(线程和线程池的好处)

JavaEE传送门

JavaEE

JavaEE——进程与线程的关系

JavaEE——No.2 多线程案例(内含线程池)


目录

  • 线程小知识
    • 对比线程和进程
      • 1. 线程的优点
      • 2. 进程与线程的区别
    • 线程池
      • 1. 线程池的优点
      • 2. ThreadPoolExecutor
      • 3. 一个小问题


线程小知识

对比线程和进程

1. 线程的优点

  1. 创建一个新线程的代价, 要比创建一个新进程小得多
  2. 与进程之间的切换相比, 线程之间的切换需要操作系统做的工作要少很多
  3. 线程占用的资源要比进程少很多
  4. 能充分利用多处理器的可并行数量
  5. 在等待慢速 I/O 操作结束的同时, 程序可执行其他的计算任务
  6. 计算密集型应用, 为了能在多处理器系统上运行, 将计算分解到多个线程中实现
  7. I/O 密集型应用,为了提高性能,将 I/O 操作重叠。线程可以同时等待不同的 I/O 操作

2. 进程与线程的区别

进程 线程
系统进行资源分配和调度的一个独立单位 线程是程序执行的最小单位
有自己的内存地址空间 只独享指令流执行的必要资源,如寄存器和栈
\ 同一进程的各线程间共享内存和文件资源,可以不通过内核进行直接通信
创建、切换及终止效率较低 创建、切换及终止效率更高

线程池

1. 线程池的优点

在之前的文章中提过, 如果线程创建的速率进一步的频繁了, 此时线程创建销毁的开销仍然不能忽略.

此时, 我们用线程池来进一步优化这里的速度. 在一个池子中创建好很多线程, 当需要执行任务的时候, 不需要重新创建线程了, 只需要直接从池子里取一个现成的线程, 直接使用. 用完, 也不必释放线程, 而是直接还回到线程池里.

那么为什么从池子里取, 要比创建新线程快呢?

  • 创建线程, 是要在操作系统内核中完成的, 涉及到 用户态 -> 内核态 的切换操作, 这个操作是存在一定的开销的

如图: 我们的计算机大概是这样的结构

JavaEE——线程小知识(线程和线程池的好处)_第1张图片

应用程序发起的一个 创建线程 的行为, 线程本质上是 PCB, 是内核中的数据结构.

  • 应用程序就需要通过系统调用, 进入操作系统内核中执行
  • 内核完成 PCB 的创建, 把 PCB 加入到调度队列中, 然后再返回给应用程序

JavaEE——线程小知识(线程和线程池的好处)_第2张图片

  • 从线程池取线程, 或者把线程放回线程池, 这是纯 用户态 实现的逻辑.

# 注意 #

创建进程, 也是通过内核完成的. 创建线程和创建进程都要经历 用户态 -> 内核态, 这个过程

  • 用户态, 每个进程都是自己执行自己的逻辑
  • 内核态, 一个系统里只有一份内核再执行逻辑, 这个内核要给所有的进程都执行一些服务

总结: 使用线程池是纯用户态操作, 要比创建线程 (经历内核态的操作) 要快.


2. ThreadPoolExecutor

JavaEE——线程小知识(线程和线程池的好处)_第3张图片

相关参数解释

JavaEE——线程小知识(线程和线程池的好处)_第4张图片

标准库中的拒绝策略

JavaEE——线程小知识(线程和线程池的好处)_第5张图片

  • 中断策略 (抛出一个拒绝执行异常)

比如:

外卖员是一个线程池, app 给外卖员安排任务. 任务已经很多了, 外卖员已经送不完了. 超时要扣钱了, 外卖员哇的一声就哭了, 不干了, 罢工了.

  • 调用者执行任务策略

比如:

还是这个外卖员, app 安排的工作过多, 做不了了, 外卖员让 app 自己干. 如果 app 自己能干, 他就自己干了, 如果 app 不干, 就丢弃任务.

  • 丢弃最早的任务策略

比如:

外卖员现在要送三个外卖: 外卖1, 外卖2, 外卖3. 这是又接到一单, 外卖4. 外卖员做不了. app 发消息通知外卖员, 外卖1 不着急, 先送 外卖4.

  • 丢弃最新的任务策略

比如:

外卖员现在要送三个外卖: 外卖1, 外卖2, 外卖3. 这是又接到一单, 外卖4. 外卖员做不了. app 发消息通知外卖员, 外卖4 不着急, 还是继续先送 外卖1.


3. 一个小问题

线程池可以自定义线程数目, 那在实际开发中, 线程池的线程数目, 如何确定 ?

在这里是不好确定出具体个数的, 因为

  1. 主机的 CPU 的配置, 不确定
  2. 程序的执行特点, 不确定

有些程序代码急需要进行很多 CPU 密集型任务, 有需要很多 IO 任务.

如果任务 100% 是 CPU 密集型的话, 线程数目最多也就是 N, 更大就没意义了, CPU 已经被占满了.

如果任务 10% 是 CPU 密集型, 90% 都在操作 IO , 线程数目设置成 10N 也是没关系的.

(在工作中实际的处理方案, 是进行试验验证, 针对程序进行性能测试, 分别给线程池设置成不同的数目, 分别记录每种情况下, 程序的一些核心性能指标和系统负载情况)


(( ◞•̀д•́)◞⚔◟(•̀д•́◟ ))

以上就是今天要讲的内容了,希望对大家有所帮助,如果有问题欢迎评论指出,会积极改正!!
在这里插入图片描述
加粗样式

这里是Gujiu吖!!感谢你看到这里
祝今天的你也
开心满怀,笑容常在。

你可能感兴趣的:(JavaEE,java-ee,java)