• 1、线程含义及状态

    线程

    线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。

    线程是程序中一个单一的顺序控制流程。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程。

    线程状态

    线程状态在网上或者书籍中,大体有五种或六种甚至有七种的说法。

    大体主要区别在runnable和running,seelp和wait的归类上有差异。

    五种(书籍及日常所说):

    1、 创建状态:在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态;
    2、 就绪状态:当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态;
    3、 运行状态:线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码;
    4、 阻塞状态:线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行sleep,suspend,wait等方法都可以导致线程阻塞;
    5、 死亡状态:如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡对于已经死亡的线程,无法再使用start方法令其进入就绪;

    六种(Java api中解释):

    6、 NEW:至今尚未启动的线程处于这种状态;
    7、 RUNNABLE:正在Java虚拟机中执行的线程处于这种状态;
    8、 BLOCKED:受阻塞并等待某个监视器锁的线程处于这种状态;
    9、 WAITING:无限期地等待另一个线程来执行某一特定操作的线程处于这种状态;
    10、 TIMED_WAITING:等待另一个线程来执行取决于指定等待时间的操作的线程处于这种状态;
    11、 TERMINATED:已退出的线程处于这种状态;



  • 2、Thread、Runnable、ThreadLocal


    Thread

    public class Thread implements Runnable

    1、 线程是程序中的执行线程Java虚拟机允许应用程序并发地运行多个执行线程;
    2、 每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程;
    3、 创建新执行线程有两种方法一种方法是将类声明为Thread的子类该子类应重写Thread类的run方法newThread().start()另一种方法是声明实现Runnable接口的类该类然后实现run方法newThread(Runnable实现类实例).start();

    推荐使用声明实现 Runnable 接口的类。符合面向接口编程思想。

    常用构造方法

    Thread()分配新的 Thread 对象。
    Thread(Runnable target)分配新的 Thread 对象。
    Thread(Runnable target, String name)分配新的 Thread 对象。
    Thread(String name)分配新的 Thread 对象。

    常用方法

    Thread currentThread():返回对当前正在执行的线程对象的引用。

            public static native Thread currentThread()//native方法

    void sleep(long millis) :在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。不释放锁。


            public static native void sleep(long millis) throws InterruptedException;//native方法

    void yield():暂停当前正在执行的线程对象,并执行其他线程,且只能让同优先级的线程有执行的机会。不释放锁。


            public static native void yield();

    void join(long millis) :等待该线程终止的时间最长为 millis 毫秒。join(0)等价于join()。

    {D3CE83A1-D49B-4059-BC72-4A6B1F5581FA}.png

    void start(): 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。

    {A51CF454-5A08-4E1E-8D30-319303DA5E38}.png

    void interrupt():中断线程。

    {280FCD73-0F92-4CA3-B9B6-E1E52C2562A2}.png

    destroy() 、resume()、suspend() 、stop() 已过时且不安全,故不作介绍。

    public interface Runnable

    1、 接口实现类类必须定义一个称为run的无参数方法;
    2、 设计该接口的目的是为希望在活动时执行代码的对象提供一个公共协议;
    3、 Runnable为非Thread子类的类提供了一种激活方式通过实例化某个Thread实例并将自身作为运行目标,就可以运行实现Runnable的类而无需创建Thread的子类大多数情况下,如果只想重写run()方法,而不重写其他Thread方法,那么应使用Runnable接口这很重要,因为除非程序员打算修改或增强类的基本行为,否则不应为该类创建子类;

    {B862F578-CCD4-4505-A6FE-279533D58FFE}.png

    ThreadLocal

    public class ThreadLocal

    1、 该类提供了线程局部(thread-local)变量这些变量不同于它们的普通对应物,因为访问某个变量(通过其get或set方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本;
    2、 ThreadLocal实例通常是类中的privatestatic字段,它们希望将状态与某一个线程(例如,用户ID或事务ID)相关联;

    成员变量

    {019F1777-EAD1-4D8C-A317-D959452AB273}.png

    构造方法


    /**

     * 创建一个线程本地变量。

     */

    public ThreadLocal() {

    }

    方法

    T get()返回此线程局部变量的当前线程副本中的值。
    void set(T value)将此线程局部变量的当前线程副本中的值设置为指定值。大部分子类不需要重写此方法,它们只依靠 initialValue() 方法来设置线程局部变量的值。
    void remove()移除此线程局部变量当前线程的值。如果此线程局部变量随后被当前线程 读取,且这期间当前线程没有 设置其值,则将调用其 initialValue() 方法重新初始化其值。这将导致在当前线程多次调用 initialValue 方法。
    T initialValue()返回此线程局部变量的当前线程的“初始值”。

    ThreadLocal由其内部类ThreadLocalMap实现的。每个ThreadLocal维护一个ThreadLocalMap实例,key为ThreadLocal实例本身,value是真正需要存储的Object。

    先设值

    {46EA4CE5-0361-408D-B041-F520A35EEB4D}.png


    再取值

    {9C37A14D-035D-45F2-874D-AE0A8DF155F0}.png



  • 3、Callable、Future、RunnableFuture、FutureTask


    Callable

    public interface Callable

    1、 返回结果并且可能抛出异常的任务;
    2、 Callable接口类似于Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的但是Runnable不会返回结果,并且无法抛出经过检查的异常;
    3、 Executors类包含一些从其他普通形式转换成Callable类的实用方法;

    接口中定义的唯一一个方法。

         call() throws Exception;

    与FutureTask结合使用。

    与Runnable区别:

    1、 实现Callable接口能返回结果;而实现Runnable接口不能返回结果;
    2、 实现Callable接口可抛出经过检查的异常;而实现Runnable接口不能抛出异常;

    Future

    public interface Future

    1、 Future表示异步计算的结果;
    2、 它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果计算完成后只能使用get方法来获取结果,如有必要,计算完成前可以阻塞此方法取消则由cancel方法来执行还提供了其他方法,以确定任务是正常完成还是被取消了一旦计算完成,就不能再取消计算;
    3、 如果为了可取消性而使用Future但又不提供可用的结果,则可以声明Future形式类型、并返回null作为底层任务的结果;

    通俗地理解就是可以对正在执行的任务进行维护操作(取消任务、获取任务执行结果、判断任务是否已完成等)。

    接口方法

    boolean cancel(boolean mayInterruptIfRunning):试图取消对此任务的执行。

            boolean cancel(boolean mayInterruptIfRunning);

    boolean isCancelled():如果在任务正常完成前将其取消,则返回 true。

    boolean isDone():如果任务已完成,则返回 true。 可能由于正常终止、异常或取消而完成,在所有这些情况中,此方法都将返回 true。

    Vget():如有必要,等待计算完成,然后获取其结果。

            V get() throws InterruptedException, ExecutionException;

    Vget(long timeout, TimeUnit unit):如有必要,最多等待为使计算完成所给定的时间之后,获取其结果(如果结果可用)。

            V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;


    RunnableFuture

    public interface RunnableFuture extends Runnable, Future

    1、 作为Runnable的Future成功执行run方法可以完成Future并允许访问其结果;

    唯一方法

            void run();
    
    FutureTask

    public class FutureTask implements RunnableFuture

    1、 可取消的异步计算;
    2、 利用开始和取消计算的方法、查询计算是否完成的方法和获取计算结果的方法,此类提供了对Future的基本实现;
    3、 可使用FutureTask包装Callable或Runnable对象因为FutureTask实现了Runnable,所以可将FutureTask提交给Executor执行;
    4、 仅在计算完成时才能获取结果;如果计算尚未完成,则阻塞get方法一旦计算完成,就不能再重新开始或取消计算;

    成员变量

            private final Sync sync;

    构造方法

    {3405F074-96BA-4C66-B533-C6F9256A5C04}.png

    内部类Sync

    {37983EAA-CF23-4A12-B17C-7037E993A3ED}.png

    方法

    boolean cancel(boolean mayInterruptIfRunning):试图取消对此任务的执行。

    {71941314-0FD9-4DB5-AB33-AF41071BC81C}.png


    Vget():如有必要,等待计算完成,然后获取其结果。

    {85C0403E-9248-4960-AC7C-291F161E878B}.png

    boolean isCancelled():如果在任务正常完成前将其取消,则返回 true。

    {156776EB-7FFA-4F02-A0CE-B17F909CE2FA}.png


    boolean isDone():如果任务已完成,则返回 true。

    {5831F76F-CFB7-4208-9583-E37A3B25C904}.png


    void run(): 除非已将此 Future 取消,否则将其设置为其计算的结果。

    {55617F5A-607E-4E36-BB81-0DB39C31B6DF}.png


    FutureTask还提供了受保护的runAndReset、set、setException方法,及默认实现不执行任何操作的done方法,便于自定义任务类。

    从源码可知,FutureTask对线程的操作,都是通过内部类Sync实现的,其中通过CAS无锁操作维护线程状态,volatile Thread runner 保证当前线程任务的内存可见性,任务执行完成返回的结果存储在V result中。

    总结:

    由于FutureTask继承了Callable和Runnable,故既可作为一个Runnable直接被Thread执行,也可作为Future用来得到Callable的计算结果。

    FutureTask一般配合ExecutorService来使用,也可以直接通过Thread来使用。

    当调用cancel(true)方法的时候,最终执行Thread.interrupt()方法,而interrupt()方法只是设置中断标志位,如果runner处于sleep()、wait()或者join()处理中则会抛出InterruptedException异常。

    FutureTask提供可得到返回结果及 protected 功能,让FutureTask扩展性增强。

    Callable、Future、FutureTask关系。

    FutureTask实现Future接口,可以对任务进行维护操作,包装 Callable可得到任务执行完成后计算的结果。