线程池技术分享

本篇文章将从三个部分来给大家介绍线程以及线程池;

  1. 线程
    线程与进程区别&由来
    线程状态
    如何使用HOW
  2. 线程池what & why& how
    何谓池化?
    JAVA中的线程池介绍
    线程池 优雅重启和优雅关闭

1.1.1 区别

进程是资源分配的最小单位,线程是cpu执行的最小单位,线程是进程的一个实体,包含在进程之中;

1.1.2 进程的由来

在这里插入图片描述

从操作系统的发展了解进程:
1:计算发明之前:
计算机发明早起主要是为了解决大量的数学计算问题,程序员将对应于程序和数据的已穿孔的纸带(或卡片)装入输入机,然后启动输入机把程序和数据输入计算机内存,接着通过控制台开关启动程序针对数据运算。计算完毕后,输出机输出计算结果;用户取走结果并卸下纸带(或卡片)后,才让下一个用户上机。
在这里插入图片描述

2:批处理操作系统的出现:
批处理操作系统又分为单道处理操作系统和双道处理操作系统;我们来简单的讲述下:
单道批处理操作系统:
为了解决大量手工操作的耗时性,实现作业(程序,数据,指令)的自动过渡,接着又出现了单道批处理系统。单道批处理系统与原来手动操作主要的区别是在输入机与主机之间增加了一个存储设备磁带(盘)(下图,红色虚线部分),并在计算机设备上配上监督程序,其具体的运行方式是把批量操作的作业输入到磁带上,然后有监督器调出磁带上的第一个作业任务装入内存,并把控制权交给第一个作业任务,第一个任务执行介绍后,将控制权归还给监督程序,监督程序接着调度磁带上的第二个作业;计算机系统就这样自动地一个作业一个作业地进行处理,直至磁带上的所有作业全部完成。还是以上文吃饭、洗澡、睡觉这三个指令为例子,我们可以得到下图:
在这里插入图片描述
多道批处理操作系统:
可以发现单道批处理操作系统是存在问题的,即正在执行的任务如果有大量I/O任务,那么此时CPU是空闲的,此时B任务连被调度的机会都没有;为了解决单道批处理系统因为输入/输出(I/O)请求后,导致计算机等待I/O完成而造成的计算机的资源的浪费。接下来又出现了多道批处理系统。多道批处理系统与单道批处理系统的主要区别是在内存中允许一个或多个作业,当一个作业在等待I/O处理时,多批处理系统会通过相应调度算法调度另外一个作业让计算机执行。从而使CPU的利用率得到更大的提高。如下图所示:
在这里插入图片描述

1.1.3 分时操作系统- 进程的出现

在多道批处理系统中引申出了一个非常重要的模式,即允许多个作业进入内存并运行。由于在内存中存储了多个作业,那么多个作业如何进行区分?当某个作业因为等待I/O暂停时,怎么恢复到之前的运行状态呢?
所以这个时候,聪明的人们就发明了进程这一概念,用进程来保存每个作业的数据与运行状态,同时对每个进程划分对应的内存地址空间(代码、数据、进程空间、打开的文件),并且要求进程只能使用它自己的内存空间。那么就可以达到作业的区分及恢复。

1.1.4 线程的由来

那么此时想必聪明的你一定对进程的由来,有了个大致的认识,那么你有没有想过,既然进程已经解决了我们传统的手工操作多,耗时性长,资源浪费问题,进程不就挺完美的嘛,为什么还需要线程呢?别急,答案,会慢慢的告诉你。
那么首先我们看看进程会带来哪些问题:
在这里插入图片描述
问题一: 多个子任务同时执行会带来并发问题; 多道批处理系统所引入的进程的概念,确实提高了计算机的运行效率,但是单单使用进程来处理程序的并发的弊端也越来与突出,因为一个进程在一个时间段内只能做一件事情。如果某个程序有多个任务,只能逐个执行这些任务。
什么意思呢?比如功能相近的两个任务A、任务B,如果起两个进程去执行,那么A任务进程和B任务进程如果同时针对磁盘文件内容进行修改的话,那么会出现问题的;
问题二: 进程上下文切换很重,代价太大了;还是以上文提到的吃饭为例子。假设在吃饭进程中包含两个任务,一个看电视任务,一个吃饭任务。现在我们希望计算机一边执行吃饭任务,一边执行看电视任务。那么根据多道批处理系统的运行规则,计算机实际调度是以进程为调度单位的,那么我们想一边吃饭,一边看电视的行为,只能拆分为两个进程。但是我们知道进程中存储了大量信息(数据,进程运行状态信息等)。那么当计算机进行进程切换的时候,必然存在着很大的时间与空间消耗(因为每个进程对应不同内存地址空间,进程的切换,实际是处理器处理不同的地址空间)。如果不拆分为两个进程,吃饭这两个任务在同一个进程中,那么这两个任务必然是依次执行的,这又违背了我们一边看电视一边吃饭的初衷。
那么问题来了,我们是否可以实现进程中任务的切换,又可以避免进程切换内存地址空间呢?聪明的人们又进一步的发明了线程这一概念。用线程表示进程中的不同任务,同时又将计算机实际调度的单元转到线程。这样就避免了进程的内存地址空间的切换,也达到了多任务的并发执行。具体如下图所示:
在这里插入图片描述
前面讲解了进程与线程的由来,有可能大家现在还有一丝疑惑,下面就让我们一起来总结一下进程与线程的关系。

  • 进程是计算机分配资源的单元,而线程是计算机调度的基本单元。
  • 一个进程由一个或多个线程组成。线程代表着进程中不同的任务。
  • 进程之间相互独立,同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)及一些进程级的资源(如打开文件和信号)
  • 进程的切换存在时空开销。

在这里插入图片描述

1.2 线程的状态

面试中面试官经常会问到,线程有几种状态呀,很多小伙伴会去百度看到5钟等各种答案,其实最好的答案,就在JDKThread类的源码中,我们翻下源码来看看具体线程有多少状态呢?

java.lang.Thread.State

/**
     * A thread state.  A thread can be in one of the following states:
     * <ul>
     * <li>{@link #NEW}<br>
     *     A thread that has not yet started is in this state.
     *     </li>
     * <li>{@link #RUNNABLE}<br>
     *     A thread executing in the Java virtual machine is in this state.
     *     </li>
     * <li>{@link #BLOCKED}<br>
     *     A thread that is blocked waiting for a monitor lock
     *     is in this state.
     *     </li>
     * <li>{@link #WAITING}<br>
     *     A thread that is waiting indefinitely for another thread to
     *     perform a particular action is in this state.
     *     </li>
     * <li>{@link #TIMED_WAITING}<br>
     *     A thread that is waiting for another thread to perform an action
     *     for up to a specified waiting time is in this state.
     *     </li>
     * <li>{@link #TERMINATED}<br>
     *     A thread that has exited is in this state.
     *     </li>
     * </ul>
     *
     * <p>
     * A thread can be in only one state at a given point in time.
     * These states are virtual machine states which do not reflect
     * any operating system thread states.
New:new Thread()后线程的状态就是新建。
Runnable:线程一旦调用start()方法,无论是否运行,状态都为Runable,注意Runable状态指示表示线程可以运行,不表示线程当下一定在运行,线程是否运行由虚拟机所在操作系统调度决定。
被阻塞:线程试图获取一个内部对象的Monitor(进入synchronized方法或synchronized块)但是其他线程已经抢先获取,那此线程被阻塞,知道其他线程释放Monitor并且线程调度器允许当前线程获取到Monitor,此线程就恢复到可运行状态。
等待:当一个线程等待另一个线程通知调度器一个条件时,线程进入等待状态。
计时等待:和等待类似,某些造成等待的方法会允许传入超时参数,这类方法会造成计时等待,收到其他线程的通知或者超时都会恢复到可运行状态。
被终止:线程执行完毕正常结束或执行过程中因未捕获异常意外终止都会是线程进入被终止状态。
参考文章:https://segmentfault.com/a/1190000016197831?utm_source=tag-newest#articleHeader6

具体关于:wait和sleep 区别? 为什么wait和notify方法要放在同步代码块中执行?讲下线程状态中的WAITING状态,什么时候会处于这个状态? 等这些面试问题,晚些我会继续推出一篇关于 线程&并发的专题进行讲解;敬请期待;

1.3 了解完线程的基本概念后,那么如何使用呢?看JAVADOC!!

* There are two ways to create a new thread of execution. One is to
 * declare a class to be a subclass of <code>Thread</code>. This
 * subclass should override the <code>run</code> method of class
 * <code>Thread</code>. An instance of the subclass can then be
 * allocated and started. For example, a thread that computes primes
 * larger than a stated value could be written as follows:
 * <hr><blockquote><pre>
 *     class PrimeThread extends Thread {
 *         long minPrime;
 *         PrimeThread(long minPrime) {
 *             this.minPrime = minPrime;
 *         }
 *
 *         public void run() {
 *             // compute primes larger than minPrime
 *             &nbsp;.&nbsp;.&nbsp;.
 *         }
 *     }
 * </pre></blockquote><hr>
 * <p>
 * The following code would then create a thread and start it running:
 * <blockquote><pre>
 *     PrimeThread p = new PrimeThread(143);
 *     p.start();
 * </pre></blockquote>
 * <p>
 * The other way to create a thread is to declare a class that
 * implements the <code>Runnable</code> interface. That class then
 * implements the <code>run</code> method. An instance of the class can
 * then be allocated, passed as an argument when creating
 * <code>Thread</code>, and started. The same example in this other
 * style looks like the following:
 * <hr><blockquote><pre>
 *     class PrimeRun implements Runnable {
 *         long minPrime;
 *         PrimeRun(long minPrime) {
 *             this.minPrime = minPrime;
 *         }
 *
 *         public void run() {
 *             // compute primes larger than minPrime
 *             &nbsp;.&nbsp;.&nbsp;.
 *         }
 *     }
 * </pre></blockquote><hr>
 * <p>
 * The following code would then create a thread and start it running:
 * <blockquote><pre>
 *     PrimeRun p = new PrimeRun(143);
 *     new Thread(p).start();
 * </pre></blockquote>
 * <p>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值