这就是线程

1. 前言

    线程是处理器的基本调度单位,是比进程更轻量级的调度单位。线程的引入可以把一个进程的资源分配和执行调度区分开,线程间可以共享进程资源,又可以独立调度。

Java 线程类在线文档:https://docs.oracle.com/en/java/javase/15/docs/api/
我一看是 JDK15,啪的一下点进来了,很快啊。欸,不消费马老师了,看着正在跑项目的 JDK8,我的眼角湿润了

2. 实现线程的三种方式

2.1 实现线程的三种方式

  • 使用内核线程实现
  • 使用用户线程实现
  • 用户线程+轻量级进程混合实现

2.2 用户线程+轻量级进程混合实现介绍

在这里插入图片描述

图2-1、用户线程和轻量级进程多对多线程模型图
  • 内核线程(KLT,Kernel-Level Thread)
        直接由操作系统内核(Kernel)支持的线程。
  • 轻量级进程(LWP,Light Weight Process)
        轻量级进程是我们通常意义上所讲的线程,是基于内核线程的一种高级接口,程序一般不直接使用内核线程,使用轻量级进程。
  • 用户线程(UT,User Thread)
        不是内核线程的线程可以看作为用户线程。

    内核线程由内核完成线程切换,内核通过线程调度器对线程进行调度,并负责将线程的任务映射到各个处理器上。
    每个轻量级进程都由一个内核线程支持,是轻量级线程和内核线程一对一的线程模型。所以轻量级进程是存在受限于内核线程的,内核资源有限,支持的轻量级进程也是有限。一个程序进程需要多个轻量级线程支持,这种线程模型受内核资源限制比较大。
    用户线程和建立、同步、消费、调度不需要内核的帮助,是快速且低耗的,支持更大规模的线程数量。进程与用户线程的关系属于一对多的线程模型。用户线程没有内核的支援,需要解决线程调度,阻塞等问题,比较复杂,这种仅使用用户线程的线程模型也渐渐被弃用。
    用户线程和轻量级进程混合实现,两者之间的关系为 N:M,这种关系属于多对多的线程模型.

2.3 线程调度的两种模式

线程调度指系统为线程分配处理器使用权的过程。

  • 协同式线程调度
        实现简单,线程执行完成主动通知系统进行线程切换;线程执行时间系统不可控,如果线程阻塞,则会一直占用处理器资源。
  • 抢占式线程调度
        交由系统分配时间,线程切换可由程序进行控制,比如 Java 的 Thread.yeild() 线程让步方法。线程执行时间系统可控。

3. Java 中的线程调度及状态

在这里插入图片描述

图3-1、Java 线程状态转换图

3.1 Java 中的线程调度

    是抢占式调度,支持线程优先级,优先级高的更容易被先执行;支持线程让步等

3.2 Thread 线程对象的状态

  • 新建(New)
        创建后且未调用 start() 方法启动线程的初始状态
  • 运行(Runnable)
        Java 中的运行状态包括操作系统线程状态中的 Runnable 和 Ready;即 Java 中的运行状态包含,线程正在运行或者线程准备状态下正在等待分配处理器资源。
  • 无限期等待(Waiting)
        处于无限期等待的线程,不会被分配处理器资源去执行,需要等待其他线程显式的去唤醒。
        Object.wait()、Thread.join()、LockSupport.park()方法可使线程进入无限期等待状态。
  • 限期等待(Timed Waiting)
        该状态下,线程也不会被分配处理器资源,但是可以不需要其他线程显式唤醒,当前线程一段时间(时间大小可自定义)后会由系统自动唤醒。
        Thread.sleep(timeOut)、Object.wait(timeOut)、Thread.join(timeOut)、LockSupport.parkNanos()、LockSupport.parkUntil()方法可使得线程进入限期等待状态。
  • 阻塞(Blocked)
        线程阻塞,需要等待获取到一个排他锁,这个事件将在另一个线程放弃这个排他锁时发生。
  • 结束(Terminated)
        线程执行结束,或者已终止的线程

阻塞状态与等待状态的区别
    等待线程,需要其他线程来唤醒,或者一定等待期限后由系统唤醒进入运行状态。阻塞状态需要获取其他线程释放被占用的排他锁才可进入运行状态。

4. Thread 线程类的构造方法

4.1 演示代码

/**
 * @className: ThreadConstructor
 * @description: Thread Constructor
 **/
public class ThreadConstructor {

    public static void main(String[] args) {
        init();
    }

    private static void init() {
        // target runnable
        final Runnable targetRunnable = new Runnable() {
            @Override
            public void run() {
                // to do something
            }
        };
        // mainThread's threadGroup; 
        final ThreadGroup mainThreadGroup = Thread.currentThread().getThreadGroup();
        final String thread_04Name = "Thread-Constructor-04";
        final String thread_05Name = "Thread-Constructor-05";
        final String thread_06Name = "Thread-Constructor-06";
        final String thread_07Name = "Thread-Constructor-07";
        final String thread_08Name = "Thread-Constructor-08";
        // init stack size, Beyond method stack throw java.lang.StackOverflowError
        long stackSize = 1 << 24;

        Thread thread_01 = new Thread();
        Thread thread_02 = new Thread(targetRunnable);
        Thread thread_03 = new Thread(mainThreadGroup, targetRunnable);
        Thread thread_04 = new Thread(thread_04Name);
        Thread thread_05 = new Thread(mainThreadGroup, thread_05Name);
        Thread thread_06 = new Thread(targetRunnable, thread_06Name);
        Thread thread_07 = new Thread(mainThreadGroup, targetRunnable, thread_07Name);
        Thread thread_08 = new Thread(mainThreadGroup, targetRunnable, thread_08Name, stackSize);
        thread_01.start();
        thread_02.start();
        thread_03.start();
        thread_04.start();
        thread_05.start();
        thread_06.start();
        thread_07.start();
        thread_08.start();
        mainThreadGroup.list();
    }
}

4.2 入参说明

  • targetRunnable
        是接口 Runnable 的实现,需要实现 run() 方法。线程交由 JVM 管理,线程启动后,可运行的线程会执行 run() 的内部逻辑。
  • threadGroup
        线程组,用来管理线程的,由线程组成;线程对象创建时可指定所属线程组 threadGroup; 未指定线程组则为 null
  • name
        线程名称,默认名称为 Thread-index,index 属于[0, +∞)。线程名称支持自定义,允许重复,不可为空;线程 ID 自增唯一。
  • stackSize
        指定方法栈大小,避免内存泄漏。超出指定大小则会抛出 java.lang.StackOverflowError

关键代码演示:

    private static long threadSeqNumber;
    private static synchronized long nextThreadID() {
        return ++threadSeqNumber;
    }
    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }
    public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize) {
        init(g, target, name, stackSize, null, true);
    }
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        // ... ...
        Thread parent = currentThread();
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
            if (security != null) {
                g = security.getThreadGroup();
            }
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }
        // ... ...
        this.group = g;
        this.daemon = parent.isDaemon();
        this.priority = parent.getPriority();
        /* Set thread ID */
        tid = nextThreadID();
    }

5. Thread 线程的两种实现方式

5.1 作为子类继承 Thread 类

class ThreadByExtendsThread extends Thread {
    @Override
    public void run() {
        // super.run() or custom to do something
        super.run();
    }
}

eg: 线程调用方式

    ThreadByExtendsThread thread = new ThreadByExtendsThread();
    thread.start();

5.2 作为实现类实现 Runnable 接口

class ThreadByImplementsRunnable implements Runnable {
    @Override
    public void run() {
        // custom to to something
    }
}

eg: 线程调用方式

    ThreadByImplementsRunnable runnable = new ThreadByImplementsRunnable();
    Thread thread = new Thread(runnable);
    thread.start();

Power By niaonao

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 博客之星2020 设计师:CY__ 返回首页