线程安全案例 --- 线程池

小王学习录

  • 今日鸡汤
  • 什么是线程池
  • 为什么需要线程池
    • 1. 协程
    • 2. 线程池
    • 3. 什么是用户态和内核态
  • 使用线程池 --- java标准库
    • 1. 线程池的创建
    • 2. 工厂模式
    • 3. 线程池的使用
  • ThreadPollExecutor类
    • 构造方法
      • 1. corePoolSize, maximumPoolSize 线程
      • 2. long keepAliveTime, TimeUnit unit 时间
      • 3. BlockingQueue workQueue 任务队列
      • 4. ThreadFactory threadfactory 创建线程
      • 5. RejectedExecutionHandler handler 拒绝策略
  • 实现线程池
  • 编外: Runnable介绍

今日鸡汤

爱人如养花, 最好的花匠是自己

什么是线程池

线程池是对线程进行管理和复用的机制. 在程序中创建一组线程, 当有任务需要执行时, 随机分配任务给空闲线程. 而不单独为一个任务创建线程, 这提高了线程的利用率, 减小了线程使用时创建和销毁的开销.
线程池的管理结构, 线程对象状态, 线程队列保存在java虚拟机的堆中, 包括了ThreadPollExecutor中的字段. 而线程执行时的线程状态, 栈信息保存在内存中.

为什么需要线程池

即使引入了相对来说轻量的线程, 但是随着对并发要求以及系统性能要求的提高, 实现一种比线程更轻量的并发问题解决方式显得尤为重要, 如今出现的方法有两种:协程线程池

1. 协程

协程(纤程): 在java标准库中暂时并没有支持协程. 当下热度较高的Go语言支持了协程, 这应该也是其发展至今的一条因素吧. 期待java大佬早日在标准库中实现协程.
线程安全案例 --- 线程池_第1张图片

2. 线程池

第二种方法就是引进线程池. 创建和销毁线程的操作是由操作系统实现的, 有了线程池, 要用到线程时可以直接从池中拿, 也没必要销毁线程, 不用时放回到线程中. 从池中取和放的操作用户通过代码就能实现, 不用通过内核. 这种通过程序员写代码来操作线程叫用户态.

3. 什么是用户态和内核态

在这里需要说一下用户态和内核态的区别:

  1. 内核态: 内核态的操作是由操作系统内核来完成的, 操作系统提供给程序api, 称作为系统调用, 程序通过系统调用来驱使内核进行一些操作. 系统调用中的代码与内核相关, 开发程序员无法对其进行操作.
  2. 用户态: 程序执行是由程序员写代码来控制的, 执行什么, 怎么执行都是由程序员来指定.
  3. 内核态相比于用户态, 其操作更不可控. 因为内核并不只是为一个应用程序服务, 要对多个应用程序服务, 程序通过系统调用来驱使内核进行一些操作时, 并不知道此时内核要去完成多少个任务, 也不知道自己排在第几位去执行. 相比之下, 从池中拿的这种用户态执行时更加干净利索.

使用线程池 — java标准库

1. 线程池的创建

java的标准库中是根据工厂模式来实现线程池的创建的, 看如下代码:

ExecutorService executorService = Executors.newFixedThreadPool(10);
//代码创建了一个线程池, 池里面有10个线程. 

创建的线程池中的线程默认都为前台线程
以上代码用一个类方法创建了一个对象, 构造对象被隐藏在了类方法中. 这种方法叫做工厂方法, 这个方法所属的类就是工厂类, 这样的代码使用了工厂模式. 下面对工厂模式进行简单介绍

2. 工厂模式

工厂模式也属于一种设计模式, 前面介绍过一种单例模式的设计模式, 今天来说一下工厂模式
工厂模式: 通俗的讲, 工厂模式就是用一个普通方法来代替构造方法

这种情况发生在方法重载不能用于完成当前功能. 比如:
要表示一个点的坐标, 可以有平面直角坐标系和极坐标系两种表示方法, 两种表示方式的x,y坐标都是doble类型, 参数类型, 数量和返回类型都一致, 无法使用方法重载. 此时使用两个类方法(普通方法名可以不一致, 有几种构造方法就用几个不同名的类方法)来表示两种表示方法, 在类方法中再做一些限制从而实现用平面直角坐标系和极坐标系两种方式来表示坐标.

3. 线程池的使用

线程池的使用到的是submit方法, 使用submit可以异步的向线程池中的任务队列提交任务(不必等待任务执行完毕), 从而让线程池中的空闲线程去调用提交的任务.

public class ThreadDome1 {
   
    public static void main(String[] args) {
   
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        for(int i = 0; i 

你可能感兴趣的:(操作系统,安全,开发语言,java,操作系统,线程安全,线程池,多线程)