zoukankan      html  css  js  c++  java
  • 多线程学习和补充:接口之间的关系等等

    一、概念理解

    1、进程和线程

    • 进程是操作系统级别的概念:
      • 一个系统中可以有多个进程;
    • 线程是进程中划分的概念:
      • 一个进程中可以划分多个线程;

    2、处理器:个数和多核:

    • 一个处理器在某一个时间点上永远都只能是一个线程!即使这个处理器是多核的。
      • 多核可以提升线程的执行效率,但多核不能同时运行多个线程。
    • 多个处理器才能同时运行多个线程。

    二、使用多线程:Runnable 接口和 Thread 类

    2.1、Runnable 接口

    如上:

    • Runnable 是一个功能型函数(JAVA 8 新特性)。
    • 它是一个接口;
    • 它只定义了一个 run() 方法。public abstract void run();

    官方文档:Runnable (Java Platform SE 8 )

    2.2、Thread 类

    注意:Thread 类实现了 Runnable 接口。

    具体类的学习挺复杂挺多的,后续再看和分析。

    2.3 使用多线程

    2.3.1 方式一:实现 Runnable 接口

    使用步骤

    1. 一个类 A,实现 Runnable 接口。该类需要重写 run()方法,即为线程的实现内容;
    2. 创建类 A 的对象 A-1;
    3. 将对象 A-1 作为 Thread 类的构造函数的入参,得到一个 Thread 类对象 T-1;
    4. 执行 T-1对象的 start() 方法,启动线程;
    5. 结束

    2.3.2 方式二:继承 Thread 类

    使用步骤

    1. 一个类 T, 继承 Thread 类。该类需要重写 run()方法,即为线程的实现内容;
    2. 创建类 T 的对象 T-1;
    3. 执行 T-1对象的 start() 方法,启动线程;
    4. 结束

    2.3.3 两种步骤的区别:

    继承 Thread 类比实现 Runnable 接口简洁了一步,在于

    • 继承 Thread 类会直接将 run() 方法的实现赋予到对象中。
    • 但是实现 Runnable 接口需要通过对应的构造函数将 run() 方法的实现赋予到对象中。

    具体的代码实现可以见原文:Java 多线程学习(一)Java 多线程入门 - 掘金

    三、各接口之间的关系

    各接口之间的关系:

    • Callable 接口 和 Runnable 接口
      • Callable 接口只有一个 call() 方法,这是一个泛型接口,call () 函数返回的类型就是传递进来的 V 类型。
      • Runnable 接口只有一个 run() 方法。
      • 两者无明显关系;
    • Callable 接口 和 Future接口
      • 如上图,两者也无明显关系
    • Executor 和 Runnable接口
      • 如上图,Executor 只和Runnable 有关系。execute() 方法的入参是 Runnable 。
      • Executor 和 Callable 以及 Future并无明显关系;
    • ExecutorService 接口
      • 这是一个很神奇的接口
        • 首先它继承自 Executor :意味着和 Runnable 接口有关系
      • 它通过submit()方法把 Runnable 与Callable 和 Future结合了起来
        • Runnable 与Callable作为方法入参,Future作为返回结果;
      • 它通过invokeAll()方法把 Callable 和 Future结合了起来,而且都是List的那种;
      • invokeAny()方法暂时找不到用途。

    四、其他关系:

    4.1 FutureTask 和 Future 的关系

    关系如下图,FutureTask 实现了 Future 接口和 Runnable 接口。其他就是FutureTask 自己的方法,自己的实现逻辑。
    注意:FutureTask 是 Future 接口的一个唯一实现类。

    我们重点看下FutureTask 的调用逻辑:(其他复杂实现暂时不管。)

    1. 执行线程并且得到返回结果
      • run() 方法负责线程调用,内部实际调用的是 Callable 接口。
        • 得到调用结果后调用自己的 set() 方法
        • set() 方法:将线程结果设置为自己的一个属性:outcome
    2. 取出线程结果:
      • get() 方法内部实际调用自己的 report() 方法,并返回 report() 方法的返回结果;
      • report() 方法:从自身的 outcome 属性取值并返回。

    上述就是对于 FutureTask 的具使用逻辑

    4.2 Executors 和 ScheduledThreadPoolExecutor、ThreadPoolExecutor、Executor

    4.2.1 Executors 和其他的关系 :

    • 从依赖关系上康,Executors和其他接口和类没什么关系。

    Executors 到底是做什么的?

    Executors是一个工具类,类似StringUtils等的封装。用于提供一些常用的线程池。一般网上都是说提供四种线程池:

    • newCachedThreadPool:(实现是:ThreadPoolExecutor)
    • newFixedThreadPool:(实现是:ThreadPoolExecutor)
    • newScheduledThreadPool:(实现是:ScheduledThreadPoolExecutor)
    • newSingleThreadExecutor:(实现是:ThreadPoolExecutor)

    但实际上,Executors 的方法不止这些,还有很多其他方法。不知道为什么网上这样说。
    可以看到,底层实现几乎都是ThreadPoolExecutor。那么为什么不直接使用ThreadPoolExecutor呢?因为 java doc 中不提倡直接用。

    4.2.2 其他:ScheduledThreadPoolExecutor、ThreadPoolExecutor、Executor之间的关系:

    • 首先区分接口和实现类:
      • 接口:Executor、ExecutorService、ScheduledExecutorService
      • 实现类:AbstractExecutorService、ThreadPoolExecutor、ScheduledThreadPoolExecutor
    • 然后对实现类再做区分
      • AbstractExecutorService 是线程池对象的抽象类(抽象类不能实例化)。
      • ThreadPoolExecutor、ScheduledThreadPoolExecutor可以看作是 AbstractExecutorService 的子类。

    五、参考:

    1. Java 多线程学习(一)Java 多线程入门 - 掘金
      注:开始部分对于线程、进程和处理器的概念说明很棒。
    2. Future 解析与使用 - 林老师带你学编程 - CSDN 博客
      Callable 与 Runnable的关系说的很好,还有Future 和 Callable 的关系,还有ExecutorService 的关系
    3. Java Executors 和 ThreadPoolExecutor 线程池 - xlxxcc 的专栏 - CSDN 博客
      注:说明了 Executors 和 ThreadPoolExecutor 线程池的关系。
    4. Java 并发编程:线程池的使用 - Matrix 海子 - 博客园
      注:ThreadPoolExecutor 详解。
  • 相关阅读:
    Java开发常用Util工具类
    冒泡排序
    EMQ 消息服务器
    将jar文件包打成exe文件
    mina框架搭建tcp服务器:编写自定义协议及编解码器
    SpringBoot中定时任务的设置
    SpringBoot项目+Shiro(权限框架)+Redis(缓存)集成
    计算两个时间之间的天数
    关于extern的使用
    ADC采样间隔问题+TRGO作为ADC的触发源头
  • 原文地址:https://www.cnblogs.com/buwuliao/p/11579861.html
Copyright © 2011-2022 走看看