本系列参考资料《JAVA多线程编程核心技术》
关注公众号:雨中散步撒哈拉,回复:025
进行下载资料

[toc]

一、进程与线程之间的区别

1. 何为进程?

一个可并发执行的具有独立功能的程序关于某个数据集合的一次执行过程,也是操作系统进行资源分配和保护的基本单位。简单的说,进程就是一个程序的一次执行过程。
image.png

进程
个人理解:集合体(线程),具有对外提供服务能力!
个人比喻:一个进程比喻成一个人,而线程则可以看做人的五脏六腑和其它细节!

2. 引入线程的动机和思路

操作系统采用进程机制使得多任务能够并发执行,提高了资源使用和系统效率。在早期操作系统中,进程是系统进行资源分配的基本单位,也是处理器调度的基本单位,进程在任一时刻只有一个执行控制流,这种结构称为单线程进程。单线程进程调度时存在进程时空开销大、进程通信代价大、进程并发粒度粗、不适合于并发计算等问题,操作系统引入线程机制来解决这些问题。
image.png

线程机制的基本思路是,把进程的两项功能——独立分配资源和被调度分派执行分离开来,后一项任务交给线程实体完成。这样,进程作为系统资源分配与保护的独立单位,不需要频繁切换;线程作为系统调度和分派的基本单位会被频繁的调度和切换。

3. 线程定义

线程是操作系统进程中能够独立执行的实体,是处理器调度和分派的基本单位。线程是进程的组成部分,每个进程内允许包含多个并发执行的线程。同一个进程中所有的线程共享进程的主存空间和资源,但是不拥有资源。
线程就是进程中的一个负责程序执行的一个控制单元(执行路径)。一个进程中可以有多个执行路径,称之为多线程。

线程
个人理解:多个线程组成进程,并且线程是进程中的一个负责程序执行的一个控制单元!
个人比喻:嘴巴(线程),眼睛(线程),耳朵(线程)等等,最终组成一个人体(进程)!(哈哈 个人理解哈 期待你的看法(声音))

4. 进程和线程的区别

定义方面:进程是程序在某个数据集合上的一次执行过程;线程是进程中的一个执行路径。
角色方面:在支持线程机制的系统中,进程是系统资源分配的单位,线程是系统调度的单位。
资源共享方面:进程之间不能共享资源,而线程共享所在进程的地址空间和其它资源。同时线程还有自己的栈和栈指针,程序计数器等寄存器。
独立性方面:进程有自己独立的地址空间,而线程没有,线程必须依赖于进程而存在。

二、让我们接近一下多线程

1. 创建一个普通的项目multithreadingDemo

image.png

2. 接近下多线程

创建类并编写代码如下

package com.multithreading.demo;

public class ComeNearMultithread {

    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName());
    }
}

3. 执行

image.png

发现输出为main,该输出为main线程名称,而代码中的main为main方法。俩者仅仅是名字

三、Java多线程实现的方式有四种

  1. 继承Thread类,重写run方法
  2. 实现Runnable接口,重写run方法,实现Runnable接口的实现类的实例对象作为Thread构造函数的target
  3. 通过Callable和FutureTask创建线程
  4. 通过线程池创建线程

前面两种可以归结为一类:无返回值,原因很简单,通过重写run方法,run方式的返回值是void,所以没有办法返回结果
后面两种可以归结成一类:有返回值,通过Callable接口,就要实现call方法,这个方法的返回值是Object,所以返回的结果可以放在Object对象中

四、线程的生命周期

线程是一个动态执行的过程,它也有一个从产生到死亡的过程。
image.png

image.png

  1. 新建状态:
    使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。

  2. 就绪状态:
    当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。

  3. 运行状态:
    如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。

  4. 阻塞状态:
    如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
    4.1. 等待阻塞:
    运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
    4.2. 同步阻塞:
    线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
    4.3. 其他阻塞:
    通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。

  5. 死亡状态:
    一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。

五、线程的优先级

每一个 Java 线程都有一个优先级,这样有助于操作系统确定线程的调度顺序。
Java 线程的优先级是一个整数,其取值范围是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。
默认情况下,每一个线程都会分配一个优先级 NORM_PRIORITY(5)。
具有较高优先级的线程对程序更重要,并且应该在低优先级的线程之前分配处理器资源。但是,线程优先级不能保证线程执行的顺序,而且非常依赖于平台。

Q.E.D.


只有创造,才是真正的享受,只有拚搏,才是充实的生活。