java当中的线程和操作系统的线程是什么关系?

关于操作系统的线程 linux操作系统的线程控制原语

int pthread create(pthread t *thread, const pthread attr t *attr,
void *(*start_routine) (void *), void *arg);

可以在linux系统下面通过man手册查看该函数的定义

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

参数名字

参数定义

参数解释

pthread_t *thread

传出参数,调用之后会传出被创建

线程的id

定义 pthread_t pid;继而取地址

&pid

const pthread_attr_t

*attr

线程属性,关于线程属性是linux

的知识

一般传NULL,保持默认属性

void (start_routine)

(void *)

线程的启动后的主体函数

需要你定义一个函数,然后传函

数名即可

void *arg

主体函数的参数

没有可以传nulll

linux上启动一个线程的代码:

//头文件
#include <pthread.h>
#include <stdio.h>
//定义一个变量,接受创建线程后的线程id
pthread_t pid;
//定义线程的主体函数
void* thread entity(void* arg) {
printf("i am new Thread! from c");
}
//main方法,程序入口,main和java的main一样会产生一个进程,继而产生一个main线程
int main() {
//调用操作系统的函数创建线程,注意四个参数
pthread create(&pid,NULL,thread entity,NULL);
//usleep是睡眠的意思,那么这里的睡眠是让谁睡眠呢?
//为什么需要睡眠?如果不睡眠会出现什么情况
usleep();
printf("main\n");
}

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

java代码里启动一个线程的代码

public class Example4Start {
public static void main(String[] args) {
Thread thread = new Thread(){
@Override
public void run() {
System.out.println("i am new Thread! from java ");
}
};
thread.start();
}
}

这里启动的线程和上面我们通过linux的pthread_create函数启动的线程有什么关系呢?只能去可以查看start()的源码了,看看java的start()到底干了什么事才能对比出来。start方法的源码的部分截图

可以看到这个方法最核心的就是调用了一个start0方法,而start0方法又是一个native方法,故而如果要搞明白start0我们需要查看Hotspot的源码,好吧那我们就来看一下Hotspot的源码吧,Hotspot的源码怎么看么?一般直接看openjdk的源码,openjdk的源码如何查看、编译调试?openjdk的编译我们后面会讨论,在没有openjdk的情况下,我们做一个大胆的猜测,java级别的线程其实就是操作系统级别的线程,什么意思呢?说白了我们大胆猜想 star----->start0------------>ptherad_create

我们鉴于这个猜想来模拟实现一下java启动线程

public class EnjoyThread {
public static void main(String[] args) {
//自己定义的一个类
EnjoyThread enjoythread =new EnjoyThread();
enjoythread.start0();
}
//本地方法
private native void start0();
}

这里我们让自己写的start0调用一个本地方法,在本地方法里面去启动一个系统线程,好吧我们写一个c程序来启动本地线程

本地方法的代码编写

#include <pthread.h>
#include <stdio.h>
//定义变量接受线程id
pthread t pid;
//线程的主体方法相当于 java当中的run
void* thread entity(void* arg) {
//子线程死循环
while(){
//睡眠100毫秒
usleep();
//打印
printf("I am new Thread\n");
}
}
//c语言的主方法入口方法,相当于java的main
int main() {
//调用linux的系统的函数创建一个线程
pthread create(&pid,NULL,thread entity,NULL);
//主线程死循环
while(){
//睡眠100毫秒
usleep();
//打印
printf("I am main\n");
}
}

linux上编译、运行上述C程序

编译这个程序

gcc thread.c -o thread.out -pthread

运行这个程序

./thread.out

结果如图所示

结果是两个线程一直在交替执行,得到我们预期的结果。现在的问题就是我们如何通过start0调用这个c程序,这里就要用到JNI了

java利用JNI调用本地方法

package com.enjoy.concurrency;
public class EnjoyThread {
//装载库,保证JVM在启动的时候就会装载,故而一般是也给static
static {
System.loadLibrary( "EnjoyThreadNative" );
}
public static void main(String[] args) {
EnjoyThread enjoyThread =new EnjoyThread();
enjoyThread.start0();
}
private native void start0();
}

这样完全还原java当中调用JVM源码启动线程的场景,继而可以系统的了解java线程的模型和本质

Java线程本质的更多相关文章

  1. 面试官:都说阻塞 I/O 模型将会使线程休眠,为什么 Java 线程状态却是 RUNNABLE?

    摘要: 原创出处 https://studyidea.cn 「公众号:程序通事 」欢迎关注和转载,保留摘要,谢谢! 使用 Java 阻塞 I/O 模型读取数据,将会导致线程阻塞,线程将会进入休眠,从而 ...

  2. Java 线程安全问题的本质

    原创声明:作者:Arnold.zhao 博客园地址:https://www.cnblogs.com/zh94 目录: 线程安全问题的本质 理解CPU JVM虚拟机类比于操作系统 重排序 汇总 一些解释 ...

  3. java线程 - 多线程 - 守护线程

    1.多线程执行者/处理类 都是Runnable的实现类(如自定义类实现Runnable 或 java原生的Thread.FutureTask),但最后都必须封装成Thread线程类由Thread.st ...

  4. java线程(2016-4-7)

    Thread.yield()的调用是对线程调度器(Java线程机制的一部分,可以将CPU从一个线程转移到另一个线程)的一种建议,它在声明:"我已经执行完生命周期中最重要的部分了,此刻正是切换 ...

  5. java线程内存模型,线程、工作内存、主内存

    转自:http://rainyear.iteye.com/blog/1734311 java线程内存模型 线程.工作内存.主内存三者之间的交互关系图: key edeas 所有线程共享主内存 每个线程 ...

  6. java线程详解(三)

    java线程间通信 首先看一段代码 class Res { String name; String sex; } class Input implements Runnable { private R ...

  7. Java线程与Linux内核线程的映射关系[转]

    Linux从内核2.6开始使用NPTL (Native POSIX Thread Library)支持,但这时线程本质上还轻量级进程. Java里的线程是由JVM来管理的,它如何对应到操作系统的线程是 ...

  8. java线程安全总结

    转自:http://blog.csdn.net/haolongabc/article/details/7249098 最近想将java基础的一些东西都整理整理,写下来,这是对知识的总结,也是一种乐趣. ...

  9. Java线程间通信-回调的实现方式

    Java线程间通信-回调的实现方式   Java线程间通信是非常复杂的问题的.线程间通信问题本质上是如何将与线程相关的变量或者对象传递给别的线程,从而实现交互.   比如举一个简单例子,有一个多线程的 ...

随机推荐

  1. JavaIO流,万物皆文件

    引入IO的原因 基本概念: 数据源和流的概念 IO流的概念细分 IO流的体系 IO流在Java中的流对象:inputStream .... Java对象的序列化和反序列化: 1 为什么需要序列化和反序 ...

  2. MixNet:MixConv:Mixed Depthwise Convolution kernels

  3. Java学习之反射篇

    Java学习之反射篇 0x00 前言 今天简单来记录一下,反射与注解的一些东西,反射这个机制对于后面的java反序列化漏洞研究和代码审计也是比较重要. 0x01 反射机制概述 Java反射是Java非 ...

  4. chaos;head移植版缺失python27.dll SDL2.dll问题解决

    注意 不要在目录名中有字符' ; '

  5. C++统计单词数

    [题目描述] 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数.现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在 ...

  6. idea提升效率的插件

    这篇文章用于记录idea插件.多分类记录确实可以提升效率. 1. FindBugs 虽说Idea本身提供的代码检查工具已经很强大了,但Idea提供的更多是规范性的检查,如果需要深入地检查异常,可以使用 ...

  7. ganglia访问时出现"You don't have permission to access /ganglia/ on this server"

    安装ganglia后,访问浏览器出现"You don't have permission to access /ganglia/ on this server" 按照网络上的要求配 ...

  8. 构造 IPv6 报文

    #!/usr/bin/python from scapy.all import * a=IPv6(nh=58, src='fe80::214:f2ff:fe07:af0', dst='ff02::1' ...

  9. python 基础-文件读写'r' 和 'rb'区别

    原文链接: python基础-文件读写'r' 和 'rb'区别 一.Python文件读写的几种模式: r,rb,w,wb 那么在读写文件时,有无b标识的的主要区别在哪里呢? 1.文件使用方式标识 'r ...

  10. dpkg:处理 xxx (--configure)时出错解决办法

    1.$ sudo mv /var/lib/dpkg/info /var/lib/dpkg/info_old //现将info文件夹更名2.$ sudo mkdir /var/lib/dpkg/info ...