Java内核级线程测试&内核级线程与用户级线程区别

用户级线程

有关线程管理的所有工作都由应用程序完成,内核意识不到线程的存在. 应用程序可以通过使用线程库设计成多线程程序. 通常,应用程序从单线程起始,在该线程中开始运行,在其运行的任何时刻,可以通过调用线程库中的派生例程创建一个在相同进程中运行的新线程。

用户级线程仅存在于用户空间中,此类线程的创建、撤销、线程之间的同步与通信功能,都无须利用系统调用来实现。用户进程利用线程库来控制用户线程。由于线程在进程内切换的规则远比进程调度和切换的规则简单,不需要用户态/核心态切换,所以切换速度快。由于这里的处理器时间片分配是以进程为基本单位,所以每个线程执行的时间相对减少为了在操作系统中加入线程支持,采用了在用户空间增加运行库来实现线程,这些运行库被称为“线程包”,用户线程是不能被操作系统所感知的。用户线程多见于一些历史悠久的操作系统,例如Unix操作系统

用户级线程驻留在用户空间或模式。运行时库管理这些线程,它也位于用户空间。它们对于操作系统是不可见的,因此无法被调度到处理器内核。每个线程并不具有自身的线程上下文。因此,就线程的同时执行而言,任意给定时刻每个进程只能够有一个线程在运行,而且只有一个处理器内核会被分配给该进程。对于一个进程,可能有成千上万个用户级线程,但是它们对系统资源没有影响。运行时库调度并分派这些线程。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tFsyU0IC-1588062428559)(leanote://file/getImage?fileId=5ea7e307e32aa811e1000001)]

用户线程的优点

  • 可以在不支持线程的操作系统中实现。

  • 创建和销毁线程、线程切换代价等线程管理的代价比内核线程少得多, 因为保存线程状态的过程和调用程序都只是本地过程

  • 允许每个进程定制自己的调度算法,线程管理比较灵活。这就是必须自己写管理程序,与内核线程的区别

  • 线程能够利用的表空间和堆栈空间比内核级线程多

  • 不需要陷阱,不需要上下文切换,也不需要对内存高速缓存进行刷新,使得线程调用非常快捷

线程的调度不需要内核直接参与,控制简单。

用户线程的缺点

  • 线程发生I/O或页面故障引起的阻塞时,如果调用阻塞系统调用则内核由于不知道有多线程的存在,而会阻塞整个进程从而阻塞所有线程, 因此同一进程中只能同时有一个线程在运行

  • 页面失效也会产生类似的问题。

  • 一个单独的进程内部,没有时钟中断,所以不可能用轮转调度的方式调度线程

  • 资源调度按照进程进行,多个处理机下,同一个进程中的线程只能在同一个处理机下分时复用

补充
在用户级线程中,每个进程里的线程表由运行时系统管理。当一个线程转换到就绪状态或阻塞状态时,在该线程表中存放重新启动该线程所需的信息,与内核在进程表中存放的进程的信息完全一样

内核级线程

内核线程建立和销毁都是由操作系统负责、通过系统调用完成的。在内核的支持下运行,无论是用户进程的线程,或者是系统进程的线程,他们的创建、撤销、切换都是依靠内核实现的。

线程管理的所有工作由内核完成,应用程序没有进行线程管理的代码,只有一个到内核级线程的编程接口. 内核为进程及其内部的每个线程维护上下文信息,调度也是在内核基于线程架构的基础上完成

内核线程驻留在内核空间,它们是内核对象。有了内核线程,每个用户线程被映射或绑定到一个内核线程。用户线程在其生命期内都会绑定到该内核线程。一旦用户线程终止,两个线程都将离开系统。这被称作”一对一”线程映射,

线程的创建、撤销和切换等,都需要内核直接实现,即内核了解每一个作为可调度实体的线程

这些线程可以在全系统内进行资源的竞争

内核空间内为每一个内核支持线程设置了一个线程控制块(TCB),内核根据该控制块,感知线程的存在,并进行控制

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yJ7uJVNT-1588062428565)(leanote://file/getImage?fileId=5ea7e3f1e32aa811e1000002)]

内核线程的优点:

  • 多处理器系统中,内核能够并行执行同一进程内的多个线程

  • 如果进程中的一个线程被阻塞,能够切换同一进程内的其他线程继续执行(用户级线程的一个缺点)

  • 所有能够阻塞线程的调用都以系统调用的形式实现,代价可观

  • 当一个线程阻塞时,内核根据选择可以运行另一个进程的线程,而用户空间实现的线程中,运行时系统始终运行自己进程中的线程

  • 信号是发给进程而不是线程的,当一个信号到达时,应该由哪一个线程处理它?线程可以“注册”它们感兴趣的信号

Java线程类型

测试:

package com.liaojl.test.concurrent;

import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;

/**
 * @author LiaoJL
 * @description TODO
 * @file Test4.java
 * @email jinlongliao@foxmail.com
 * @date 2020/4/28 15:09
 */
public class Test4 {
    private static final Logger log = LoggerFactory.getLogger(Test4.class);

    private ThreadPoolExecutor threadPoolExecutorLink = new ThreadPoolExecutor(
            1000,
            10002,
            2, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
    private ThreadPoolExecutor threadPoolExecutor = null;

    @Before
    public void before() {
        threadPoolExecutor = threadPoolExecutorLink;
    }

    @Test
    public void threadPoolExecutor1() throws InterruptedException {
        for (int i = 0; i < 100000; i++) {
            threadPoolExecutor.execute(() -> {
                log.info("线程:{}", Thread.currentThread().getId());
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    log.error(e.getMessage(), e);
                }
            });
        }
        Thread.sleep(10000);
    }
}

测试前:
在这里插入图片描述

测试中:
在这里插入图片描述

线程可以被操作系统感知,故Java的线程类型为内核级

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值