写在前面:了解多线程是十分必要的,这篇博文是我对该知识点的一些了解(同时也看了一些相关的Blog),用来复习并巩固相关知识。

一、什么是多线程?

        多线程,是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。在一个程序中,这些独立运行的程序片段叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理(Multithreading)”。

        多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率。线程是在同一时间需要完成多项任务的时候实现的。

二、线程的生命周期

1.新建(new Thread)
当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。

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

3.运行(running)
线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束,这个状态很复杂。

4.堵塞(blocked)
由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。该状态可以分为三种:

      4.1等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。 

      4.2同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。

      4.3其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。

5.死亡(dead)

处于运行状态的线程完成任务或遇到其他终止条件时,则切换到死亡状态。分为自然终止和异常终止。

三、线程的创建

分为以下几种:

           1.通过实现 Runnable 接口来创建线程

创建一个线程,最简单的方法是创建一个实现 Runnable 接口的类。通过实现Runnable接口,我们定义了一个子任务,然后将子任务交由Thread去执行。这种方式必须将Runnable作为Thread类的参数,然后通过Thread的start方法来创建一个新线程来执行该子任务。

           2.通过继承Thread来创建线程

创建一个线程的第二种方法是创建一个新的类,该类继承 Thread 类,然后创建一个该类的实例。

继承类必须重写 run() 方法,该方法是新线程的入口点。它也必须调用 start() 方法才能执行。

          3.通过 Callable 和 Future 创建线程

                        3.1. 创建 Callable 接口的实现类,并实现 call() 方法,该 call() 方法将作为线程执行体,并且有返回值。

                        3.2. 创建 Callable 实现类的实例,使用 FutureTask 类来包装 Callable 对象,该 FutureTask 对象封装了该 Callable 对象的 call() 方法的返回值。

                        3.3. 使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程。

                        3.4. 调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值

四、线程的优先级

        每个线程都有一个"优先级",优先级可以用整数表示,取值范围为0~10,0为最低优先级,10位最高优先级,当决定哪个线程需要调度时,首先查看是否存在优先级高的可调度线程,如果存在,就从中选择进行调度。当该线程的时间片到达之后,系统查看是否存在另一个优先级比较高的可调度线程,如果存在就调度。这样依次进行判断调度线程。