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. linux常用命令(二)服务器硬件资源信息

    内存:free -m 硬盘:df -h 负载:w/top cpu个数和核数:cat /proc/cpuinfo

  2. FPN和他的子孙们

    FPN 方框里表示top down里每层有两个卷积操作  PAN:添加一个 bottom up线 NAS-FPN:基于搜索结构的FPN  Fully-conencted FPN:全连接的FPN  Si ...

  3. ReentrantLock与synchronized 源码解析

    一.概念及执行原理   在 JDK 1.5 之前共享对象的协调机制只有 synchronized 和 volatile,在 JDK 1.5 中增加了新的机制 ReentrantLock,该机制的诞生并 ...

  4. go 字符串

    目录 前言 1.声明/赋值 2.遍历 3.操作 1.截取 2.修改 3.连接 4.比较 5.查长 6.格式化输出 4.字符串优势 跳转 前言 不做文字的搬运工,多做灵感性记录 这是平时学习总结的地方, ...

  5. 分治算法(二分查找)、STL函数库的应用第五弹——二分函数

    分治算法:二分查找!昨天刚说不写算法了,但是突然想起来没写过分治算法的博客,所以强迫症的我…… STL函数库第五弹——二分函数lower_bound().upper_bound().binary_se ...

  6. Mybatis 和 Solon 在一起的升级版

    终于说通 Solon 作者,让他为 Solon 框架添加事务注解支持了:并且把 mybatis-solon-plugin 的 @Df 注解更名为 @Db ,接地气多了(Df是什么鬼呢?新手肯定这么想. ...

  7. firewall几个常用命令

    systemctl status firewalld firewall-cmd --zone=public --add-port=80/tcp --permanent firewall-cmd --r ...

  8. Cannot instantiate the type ......的解决

    使用public abstract class MainWindow implements ActionListener{} 之后创建对象MainWindow window = new MainWin ...

  9. Javascript模块化编程(二):AMD规范 (转)

    原文作者: 阮一峰 日期: 2012年10月30日 这个系列的第一部分介绍了Javascript模块的基本写法,今天介绍如何规范地使用模块. (接上文) 七.模块的规范 先想一想,为什么模块很重要? ...

  10. getting session bus failed: //bin/dbus-launch terminated abnormally with the following error: Autolaunch error: X11 initialization failed.

    今天在调试dbus程序的时候,运行程序出现了getting session bus failed: //bin/dbus-launch terminated abnormally with the f ...