Java线程与操作系统线程的关系

2023-11-16

操作系统的线程

Linux操作系统启动一个线程

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine)(void *), void *arg);

再Linux系统中输入命令 man pthread_create后如下图所示。
在这里插入图片描述

根据man配置的信息可以得出pthread_create会创建一个线程,这个函数是Linux系统的函数,可以用C或者C++直接调用,上面信息也告诉程序员这个函数在pthread.h, 这个函数有四个参数

pthread_t *thread 传出参数,调用之后会传出被创建线程的id 定义 pthread_t pid; 继而 取地址 &pid
const pthread_attr_t *attr 线程属性,关于线程属性是linux的知识 在学习pthread_create函数的时候一般穿NULL,保持默认属性
void *(*start_routine) (void *) 线程的启动后的主体函数 相当于java当中的run 需要你定义一个函数,然后传函数名即可
void *arg 主体函数的参数 如果没有可以传NULL
  1. 在Linux上启动一个线程的代码,定义一个后缀名为 .c 的文件
// 头文件
#include <pthread.h>
#include <stdio.h>
// 定义一个变量,接受创建线程后的线程id
pthread_t pid;
// 定义线程的主体函数
void* thread_entity(void* arg)
{
    printf("I am new thread!\n");
}
// main方法,程序入口,main和java的main一样会产生一个进程,继而产生一个main线程
int main()
{
        while(1){
                // 调用操作系统的函数创建线程,注意四个参数
                pthread_create(&pid,NULL,thread_entity,NULL);
                // usleep是睡眠的意思
                usleep(100);
                printf("I am main thread...\n");
        }
}
  1. 执行命令编译 c 文件gcc -o thread.out thread.c -pthread

thread.outthread.c 编译成功之后的文件

  1. 运行:./thread.out
  2. 输出:

I am new thread!
I am main thread…
I am new thread!
I am main thread…
I am new thread!
I am main thread…
I am new thread!

一直交替执行…

假设有了上面知识的铺垫,那么可以试想一下Java的线程模型到底是什么情况呢?

Java里的线程

在Java代码里启动一个线程

/**
 * @author Itachi is_xianglei@163.com
 * @Date 2020-05-30 12:38
 */
public class Demo {

    public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("I am thread for java");
            }
        });
        t1.start();
    }
}

猜想Java中的线程就是调用操作系统的线程

这里启动的线程和上面通过Linuxpthread_create函数启动的线程有什么关系呢?

只能去查看start()的源码了,看看java的start()到底干了什么事才能对比出来.
在这里插入图片描述

可以看到这个方法最核心的就是调用了一个start0()方法,而start0()方法又是一个native方法,故而如果要搞明白start0我们需要查看Hotspot的源码, 那我们就来看一下Hotspot的源码, 一般直接看openjdk的源码,我们先做一个大胆的猜测,java级别的线程其实就是操作系统级别的线程 也就是说:

我们调用start() —> start0() —> ptherad_create() 鉴于这个猜想来模拟实现一下!

验证Java中的线程就是调用操作系统的线程

/**
 * @author Itachi is_xianglei@163.com
 * @Date 2020-05-30 12:38
 */
public class Demo {

    private native void start0();
  
    static {
        System.loadLibrary("TestThreadNative");
    }
    
    public static void main(String[] args) {
        Demo demo = new Demo();
        demo.start0();
    }
}

这里我们自己写的start0调用一个本地方法,在本地方法里面去启动一个系统线程.

System.loadLibrary()装载库,保证JVM在启动的时候就会装载。

然后我们写一个c程序来启动本地线程,文章开始时,写好了一段C程序,就用哪个吧。

// 头文件
#include <pthread.h>
#include <stdio.h>
// 定义一个变量,接受创建线程后的线程id
pthread_t pid;
// 定义线程的主体函数
void* thread_entity(void* arg)
{
    printf("I am new thread!\n");
}
// main方法,程序入口,main和java的main一样会产生一个进程,继而产生一个main线程
int main()
{
        while(1){
                // 调用操作系统的函数创建线程,注意四个参数
                pthread_create(&pid,NULL,thread_entity,NULL);
                // usleep是睡眠的意思
                usleep(100);
                printf("I am main thread...\n");
        }
}

在Linux上编译并运行上述C程序

gcc thread.c -o thread.out -pthread
./thread.out 

现在Java代码写好了,C程序也写好了。目前的问题就是我们如何通过start0调用这个c程序?

这里就要用到JNI了…(想起来了以前用Java调用易语言的DLL时候了…hhhh)

我们将写好的Java类上传至Linux系统中并编译!

在Linux下编译成clas文件:
编译: javac Demo.java 
生成class文件:Demo.class
在生成 .h 头文件:
编译: javah Demo
生成h文件:Demo.h

查看一下生成的.h文件
image.png

在第15行代码 Java_Demo_start0方法就是我们需要在C程序中定义的方法

然后继续修改.c程序,修改的时候参考.h文件,复制一份.c文件,取名threadNew.c 定义一个方法Java_Demo_start0在方法中启动一个子线程,代码如下:

// 头文件
#include <pthread.h>
#include <stdio.h>
// 记得导入刚刚编译的那个.h文件
#include "Demo.h"
// 定义一个变量,接受创建线程后的线程id
pthread_t pid;
// 定义线程的主体函数
void* thread_entity(void* arg)
{
    printf("I am new thread!\n");
}
// 这个方法要参考.h文件的15行代码
JNIEXPORT void JNICALL Java_Demo_start0(JNIEnv *env, jobject c1){
        pthread_create(&pid,NULL,thread_entity,NULL);
        while(1){
                usleep(100);
                printf("I am main thread\n");
        }
}
// main方法,程序入口,main和java的main一样会产生一个进程,继而产生一个main线程
int main()
{
        return 0;
}

把这个threadNew.c编译成为一个动态链接库,这样在java代码里会被laod到内存libTestThreadNative这个命名需要注意libxx,xx就等于我们java那边写的字符串(System.loadLibrary("TestThreadNative");)

解析类:

gcc ‐fPIC ‐I ${JAVA_HOME}/include ‐I ${JAVA_HOME}/include/linux ‐shared ‐o libTestThreadNative.so threadNew.c

如果执行上面的命令出现如下图的错误后,可尝试下面的这条命令…踩坑好久…原因未知…

gcc ./threadNew.c -I  /opt/jdk1.8.0_251/include -I /opt/jdk1.8.0_251/include/linux -fPIC -shared -o libTestThreadNative.so

做完这一系列事情之后需要把这个.so文件加入到path,这样java才能load到

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:{libTestThreadNative.so}

在这里插入图片描述

直接测试,运行我们自己写的那个java类直接测试看看结果能不能启动线程

执行命令 java Demo
image.png

牛逼!我们已经通过自己写的一个类,启动了一个线程。

但是这个线程函数体是不是java的,是C程序的。

接下来我们来实现一下这个run!

模拟实现start方法是如何调用run方法的

未完待续…(踩上面那个坑踩了太久了,弄了大半天,心好累,不想写了。以后再说吧)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java线程与操作系统线程的关系 的相关文章

  • 在Java中清空数组/处理

    除了循环遍历数组中的每个元素并将每个元素设置为 null 之外 Java 处理中是否有一个本机函数可以简单地清空数组 或销毁它 以便能够将其重新声明为新数组 There s Arrays fill myArray null 并不是说它执行的
  • Javadoc 1.5 和 1.6 中缺少 enum.valueOf(String name)

    这可能是一个愚蠢的问题 但我正在使用该方法enum valueOf String name 那里没问题 只是当我检查 javadoc 以了解有关此方法的更多信息时 我找不到它 有javadoc用于valueOf Class
  • RSA SignatureException:签名长度不正确

    我在签署 rsa 签名时遇到问题 我有一个用私钥加密的签名 然而 当我尝试使用公钥验证它时遇到问题 我得到以下异常 java security SignatureException Signature length not correct
  • 在 TestNG 中运行多个类

    我正在尝试自动化一个场景 其中我想登录一次应用程序 然后进行操作而无需再次重新登录 考虑一下 我有在特定类的 BeforeSuite 方法中登录应用程序的代码 public class TestNGClass1 public static
  • 在 Hibernate 中创建 UPDATE RETURNING 查询

    在 Oracle 中 我们可以创建一个更新查询 该查询将使用 RETURNING 子句返回更新的记录 Hibernate中有类似的功能吗 除了数据库生成的值之外 Hibernate 显然不需要返回更新的实例 因为对象传递给Session s
  • 如何修复 Android 7.0 的 Spinner 模式下的 DatePickerDialog?

    我目前正在开发一个简单的项目 其中包含一个包含在 Web 视图中的网站 具有少量交互 以提高网站本身和 Android 移动设备之间的交互性 由于该网站包含用户生日的日期输入字段 因此我希望实现一个与所有设备兼容的旋转格式的日期选择器 我尝
  • 如何将自定义日志处理程序添加到 Google App Engine?

    我正在尝试向我的 java 应用程序添加自定义日志处理程序 我已经实现了一个扩展 java util Logging Handler 类的 InnerLogger 类 在我的logging properties中声明为处理程序 handle
  • 尝试在java中的Arraylist中查找对象的所有出现

    我有一个 Java ArrayList 我需要查找其中出现的所有特定对象 ArrayList indexOf Object 方法只找到一次出现 所以看来我还需要其他东西 我认为你不需要太花哨 以下应该可以正常工作 static
  • Java 唤醒休眠线程

    我阅读了其他帖子 但没有找到我正在寻找的确切答案 所以我希望有人能给出一些澄清 我有一个将运行一段时间的程序 我有一些在后台运行的线程来执行各种任务 为了简单起见 让我们考虑 3 个线程 ThreadA每 10 秒执行一次任务 其中Thre
  • C# 中的协变和逆变

    首先我要说的是 我是一名正在学习 C 编程的 Java 开发人员 因此 我会将我所知道的与我正在学习的进行比较 我已经使用 C 泛型几个小时了 我已经能够在 C 中重现我在 Java 中知道的相同内容 除了几个使用协变和逆变的示例 我正在读
  • 如何制作无限的jscrollpane?

    我之前已经实现过拖动滚动 但是创建无限滚动窗格的最佳方法是什么 当然不会有任何滚动条 我将实现拖动滚动 我想做的是在无限表面上实现动态加载 EDIT 当然 它实际上不会是无限的 我想问如何伪造它 您可以执行以下操作 AdjustmentCl
  • 不要模拟值对象:过于通用的规则,没有解释

    以下是 Mockito 单元测试框架的引用 不要模拟值对象 为什么有人会想要这样做呢 因为实例化对象太痛苦了 gt 无效 原因 如果创造新的装置太困难 那就是一个迹象 代码可能需要一些认真的重构 另一种方法是创建 价值对象的构建者 有一些工
  • Java:使用 Java.util.concurrent 线程访问读取线程串行端口

    我正在尝试编写一个 Java 串行设备驱动程序并想使用 对我来说是新的 java util concurrent包裹 我有一种发送数据包然后等待 ACK 的方法 我打算有炭 接收在不同的线程中运行 如果接收线程收到 ACK 它应该使用发送数
  • 在Java中多次读取System.in会导致IOException?

    我正在尝试创建一个小命令行游戏来强化我在过去几个月中在 Java 中学到的一些东西 我正在尝试创建一个名为 readInput 的方法 它返回一个我可以一次又一次调用的字符串 第一次它工作正常 但第二次它会导致 IO Exception 如
  • 我们可以有虚假中断吗?

    我正在创建一个任务轮询器 每分钟都会查找任务 它看起来像这样 public class Poller private final ExecutorService e Executors newSingleThreadExecutor pub
  • scala中的协变类型参数需要在java接口中保持不变

    我有一个看起来像这样的特征 一些进一步的信息可以在我自己提出了这个相关问题 https stackoverflow com questions 3695990 inheritance and automatic type conversio
  • 方法签名中带或不带synchronized关键字的方法具有相同的字节码

    对于以下 2 个类 获得相同的 Java 字节码 java版本 java 版本 1 8 0 181 Java TM SE 运行时环境 构建 1 8 0 181 b13 Java HotSpot TM 64 位服务器 VM 内部版本 25 1
  • 使用 Runtime.getRuntime().exec() 进行重定向不起作用

    我需要从程序执行命令 命令行是可以的 我在终端试了一下 但是在程序中不行 我从我的代码中添加一个副本 File dir new File videos String children dir list if children null Ei
  • H2 用户定义的聚合函数 ListAgg 不能在第一个参数上使用 DISTINCT 或 TRIM()

    所以我有一个 DB2 生产数据库 我需要在其中使用可用的函数 ListAgg 我希望使用 H2 的单元测试能够正确测试此功能 不幸的是H2不直接支持ListAgg 但是 我可以创建一个用户定义的聚合函数 import java sql Co
  • Libgdx 和 Google 应用内购买结果

    我遵循了这些指示 https github com libgdx libgdx wiki Interfacing with platform specific code使用 ActionResolver 接口集成 Libgdx 和原生 An

随机推荐

  • win8 java 32位_java8离线安装包32位 官方最新版

    java8电脑版安装包是一款全新的java编程软件 该软件有着良好的操作性 支持多语种编程 当然也包括中文编程 支持winxp win7 win8 win10等基本微软系统进行操作 全面升级现有Java编程模式 带来一项协同开发的JVM J
  • Opencv.js+Hbuilder快速打造一个图像处理App

    一 开发工具简介 1 Opencv js Opencv 是一个常见的图像处理库 通常使用C 和python去调这个库对图像 视频流进行处理 而js版的opencv可以进一步丰富前端对于图像的处理 目前opencv js版映入了与其他版本基本
  • 安信实验室教你如何实现Windows自动安装!

    用户接入硬件后 Windows 自动下载安装或更新厂商的驱动软件 特点 1 产品的驱动程序及软件已放入微软官方驱动程序库 全世界用户都可以很快捷和方便地自动安装厂商自定义的软件 驱动通过微软官方认证 最佳安全性保障和信用背书 应用软件可以自
  • adb shell dumpsys activity activities调用信息简析

    活动栈 通过执行上面命令 可以得到类似如下格式的信息 Stack 45 type standard mode fullscreen isSleeping false mBounds Rect 0 0 0 0 Stack 0 type hom
  • Python 重命名文件或目录(os.rename)

    文章目录 1 概述 2 语法 os rename 2 1 相对路径 2 2 绝对路径 3 扩展 3 1 os 模块详解 1 概述 mermaid svg 9u1Lg7aqBXqPfILR label font family trebuche
  • Python面试常见的30个问题及答案

    Python面试问题 问题1 Python的主要功能是什么 python特性如下 解释型 动态类型 面向对象 简洁明了 免费自由 有一个庞大的社区 Q 2 区分深层和浅层拷贝 深拷贝将对象复制到另一个对象中 这意味着如果您对对象的副本进行更
  • vue-resource的$http.jsonp方法例子

    div class box div
  • svn版本回退

    SVN版本回退 当一不小心把文件改错了或者误删除了文件并提交到了服务器 我们要取消这些修改的话 首先就是将这个文件还原到上一个修订的版本的内容 revert to this rebision 然后将这个文件重新提交 那么服务器上的这个文件就
  • 集成开发工具使用

    集成开发工具使用 Intellij IDEA介绍 下载 安装 IDEA开发Java项目 IDEA快捷键 IDEA常见配置和操作的学习 1 IDEA 1 1 IDEA概述 IDEA全称Intellij IDEA 是用于Java语言开发的集成环
  • Windows Server 2016-OU组织单位日常操作

    技术无所谓贵贱 既然曾经做过就总该是要留下点什么 毕竟做技术这些年给我们留下太多太多的成长经历 总有人问这些已经很皮毛了为什么还要写 其实没那么多花哨理由 就是想着做或者不做这一块总是要对过往做个简单归总 习惯已成自然 虽然因为种种原因频繁
  • 使用http动词篡改的认证旁路

    文章目录 一 漏洞描述 二 解决建议 三 解决方法 Springboot 配置文件增加配置 编写配置类 编写过滤器 提示 以下是本篇文章正文内容 下面案例可供参考 一 漏洞描述 可能会升级用户特权并通过 Web 应用程序获取管理许可权可能会
  • C++小坑:问号表达式的输出

    文章目录 发现问题 解决方案 发现问题 本来只是想写这样一个测试是否连接成功的判断 std cout lt lt Result gt lt lt Avaliable hey you got it hell suck it lt lt std
  • DSView源码阅读笔记(持续更新中···)

    一 DSView源码阅读笔记 主线任务 将源码成功编译运行 提取示波器功能代码 添加示波器通道数量 找到接收数据部分源码 在win平台上使用qt开发环境进行代码重构 支线任务 以下笔记内容部分是猜测内容 DSView pv mainwind
  • RMS正则化 和 STD正则化 的一些见解

    研究styleganv2过程中 记录下它使用的正则化方法的一些见解 RMS 方均根 STD 标准差 stylegan 中的 pixel norm 是 RMS正则化 常见的BN层 IN层 用的是STD 在不减均值的情况下 RMS正则化公式 t
  • 针对于QT5下找不到QApplication头文件的问题界解决

    感谢前辈的总结 这里用了CTRL C CTRL V进行操作 原地址 http bbs csdn net topics 380130389 老版本 C C code 1 2 include
  • 【计算机网络】数据通信的基础知识

    通信系统的一般模型 数据通信系统的组成部分 源点 信源 产生数据 如从键盘输入 产生数字比特流 发送器 对数字比特流进行编码 如调制器 信道 是信号传输的通道 可能是一条简易的传输线路 也可能是一个复杂的网络 接收器 设备的功能与发送设备相
  • 保姆式教学-实现天空盒旋转

    目录 一 天空盒材质设置 1 在菜单栏window gt Rendering gt lighting 2 设置天空盒子材质 替换默认材质 3 认识Rotation变量 二 代码实现让天空盒转起来 在一个小Unity项目中 需要将天空盒旋转
  • 将MATLAB环境下深度学习目标检测模型部署在Jetson TX2开发板

    摘要 在MATLAB2019b环境下训练深度学习目标检测模型 利用MATLABcoder和GPUcoder生成c 代码和CUDA代码 并部署在NVIDIA Jetson TX2开发板上运行 1 利用NVIDIA SDK manager对TX
  • Python的heapq堆模块

    heapq模块 一 heapq内置模块 二 heapq 模块的使用 1 创建堆方法 2 访问堆的方法 2 获取堆的最大值 最小值方法 总结 一 heapq内置模块 Python中的heapq模块提供了一种堆队列heapq类型 这样实现堆排序
  • Java线程与操作系统线程的关系

    操作系统的线程 Linux操作系统启动一个线程 int pthread create pthread t thread const pthread attr t attr void start routine void void arg 再