java翻译器_一直编程到底在写些什么,你需要重点理解的Java编程核心内容

9b14f0f5fc077aad82865c01f798ac67.png

前言

前面纷纷总总说了不少有关Java编程的基础概念,特别是多线程编程的相关内容,主要突出了一些底层理解,很多小伙伴跟我说具体单个概念知道,但是还是不理解它们之间到底是个如何关系。虽然编写了不少具体程序,但是每天都是按照具体的语法规范和程序经典的桥段去写的,真不是到为啥要这样写,所以今天我就简单说一下我对这些问题的理解,是一个更加抽象和概括的俯瞰角度来串联一下。

JAVA高级语言编程与JRE

我们都知道Java语言是一门高级语言,在编程语言的世界里,从某种角度上来讲,所谓的高级和低级是距离人类语言的距离决定的,也就是说越接近人类语言的编程语言越高级,比如Java,C#等,而越接近机器语言的编程语言越低级,比如汇编语言,C语言等。

而我们编程的目的就是通过一些命令和数据组合来告诉机器去执行某些过程获取某些结果,而这个过程中由于人类和机器理解语言的差异,就需要一般编译过程,就拿我们Java编程语言来说,作为一种更加接近人类语言的高级编程语言,机器是不能够理解Java语言编写的内容的。

所以,要执行Java语言编写的应用程序,那么就必须在机器上安装一个翻译器,这就是我们的JRE,java语言运行环境。

JRE的最初内容只有我们安装包的lib内的几个主要的jar包文件,它们主要是定义一些跟操作系统对应的数据类型和接口调用,就是将我们的Java中定义的数据类型,转换为操作系统能够理解的数据类型,由操作系统为其分配内存空间和创建操作指令触发句柄来让CPU执行代码。

当然除了基本的数据类型和逻辑运算规则定义外,还有一些额外的内容比如扩展数据访问,安全,网络以及统一字符编码国际化之类的内容,这些都在bin/ext文件夹中的那些jar包里。从这里我们可以看出来,JRE被称为Java运行时环境,其实就是一个Java语言编写的程序到机器语言的一个翻译官。

也就是说所有Java编写的程序在操作系统里是不能运行的,因为操作系统不认识它们,所以Java就开发了一个类似母体程序,来安装到操作系统里负责要在该机器上运行的Java应用程序。

一旦Java应用程序启动,首先要调用JRE程序来读取其规定好的特有文件结构JAR,即Java存档文件。解析其内部包含的文件和资源,请求操作系统为其指定一个母体的运行内存空间,这个空间的大小是可以通过在运行程序的java命令中通过参数-Xmx来指定的。

e3083fa01eb22332de4c584bebd84972.png

JAVA程序与操作系统交互

如果我们要运行的应程序使用的运算数据量比较大,需要同时加载和设置的资源比较多,那么就有可能超出默认的JVM的内存空间,就需要在运行时指定。

理解到了这个内存空间后,我们就知道了我们编写的所有Java代码都会在这个空间中被分配Java数据类型对应的内存空间大小,设置方法允许栈,本地存储空间,程序计数器空间等。

注意这些都是在JVM程序的内部内存空间中的,是受到JVM程序管理的,如果JVM被关闭了,则它们都将不符存在,所以Java编写的程序代码又称为受托管代码。也就是说这些应用程序一般不能直接跟操作系统进行交互,而是借助JVM程序来完成。

也就是说我们编写的任何一个Java应用程序在运行时,都必须启动一个JVM进程,来作为其母体程序。一般不会允许Java代码直接去操作操作系统的内存和CPU管理。

所有Java语言定义的数据类型都是对底层机器数据类型的抽象描述,定义的一种接口描述,有JVM负责将两者粘合起来。

同时有JVM负责对于不使用的数据进行清理,而如果我们采用C/C++语言开发程序时,我们几乎是直接针对操作系统的内存和CPU管理接口来编程,没有一个母体程序来帮助,那么我们定义的每个数据结构,会被直接放到操作系统管理的内存空间中。

没有辅助程序来管理和调度它们,容易造成数据大小跟内存空间不匹配,无用数据没有被及时清理出内存空间等造成内存溢出问题。

而在Java开发中由于有个辅助的JVM母体管理能够通过某种检测处理机制来自动的对内存空间进行管理,对无用的数据进行清理也就是我们常说的JVM的垃圾回收算法GC,如此我们在使用Java语言编程时就没有必要主动的去释放数据空间,而交给JVM来完成它。

同时我们很少能够直接去操纵操作系统接口,所以Java语言相对来说出错都是在JVM母体进程里,而不会影响操作系统级别,所以Java语言也是比较安全的。

90a4c2b0ec57526d7f063796522dc2a5.png

Java程序和JVM的关系

现在我们来看一下,Java程序和JVM的关系。

当我们的Java程序进行一些比如数据运算或者输入输出操作时,Java程序作用的内存区域只是JVM进程的内存空间区域,跟操作系统管理的内存区域一般是不同的,我们应用程序要让CPU执行某个任务时,需要告诉CPU到那个内存空间中去读取数据,运算逻辑控制代码在哪里,运算结果如何处理等,这些都是以某个逻辑单元来组织的,这就是线程。

为了描述这个逻辑单元Java定义了一个抽象的描述类叫Thread。

因此我们在Java编程中声明的Thread类实例,都是在JVM管理的内存空间中的描述,真正要让CPU执行它,需要进入操作系统运行的空间中,这个过程存在着内存拷贝问题,也就是将数据从应用程序管理的内存空间拷贝到操作系统管理CPU操作内存空间进行处理,处理完成后返回给应用程序还是发送到网络上,那么这中间就有一个拷贝会原来应用程序和拷贝给网卡管理的内存空间的过程。

这个过程基本都不在我们Java应用程序所能管理的空间中。

这也就是为什么,我们定义好Thread的实例后,只能去调用start()方法,但是不知道什么时候操作系统来处理该线程内容的原因。

我们操作系统对于CPU时间的管理一般都是分片的,通过中断机制来管理CPU运算使用。由于Java程序支持运行在操作系统上JVM的一个内部线程,操作系统对于它的相应和处理都是不能准确预知的,完全由操作系统自己来决定。

c3a223b0e8815b3bec55c398fbf8959a.png

关于多线程并发编程

近年来由于CPU开始出现多核处理器,以及一台服务器可能有多个CPU一起工作,所以在多线程调度的操作系统基础上,我们编写Java应用程序时,就可以充分考虑利用多个CPU的并行运算来提高我们应用程序的执行效率。

要并行运算的一个基本要求就是其执行单元必须是在执行是互相不干涉和关联的,当然可以通过辅助程序来收集并行处理的结果统一进行管理。

这在Java编程级别体现为我们可以采用多个线程去执行同一个逻辑,而且这个逻辑是可以并行执行的。

为此Java语言为我们定义了很多相关资源定义描述内容,比如线程Thread,排队Synchronized,以及批量创建线程的线程池Executor等。

一个总的逻辑处理过程,可以先分解为多个独立的可以并行的小的逻辑单元,在互不干涉的情况下执行,然后将结果统一起来处理,得到总逻辑处理的目标。

要解决这个问题,就可能涉及到谁先谁后,资源共用,结果先后问题。同步机制其实就是让线程对同一个资源进行访问和处理时进行排队的机制。

涉及到排队就要涉及到有人维持秩序,看着谁进去了,谁要等待,谁出来了,谁可以进入的问题。这就是锁机制或看门人机制。

eaa001d5c49cdd41e8c0d5c04d3dcb14.png

关于原子操作

另外随着Java语言对于操作的更加底层深入,出现了一种被称为原子操作的定义,它是Java语言对于更加底层CPU长度数据每次拷贝运算的抽象,在特定16位或者32位操作基础上,这种操作CPU操作的最小单位,而最小单位运算无中断机制,也就是说中断机制在最小单位上是不起作用的。

如此对于者Java数据类型里可以有一些基础的数据类型作为最小单位运算,这种数据的访问一般遵循CAS模式,即试探相同就更新,不相同就再次试探。

这就给了Java语言编程以原子级别的操作,从而使其在访问某个共享资源时不用再加锁排队。符合原子操作的数据类型布尔型,Integer,Long等。

在Java中有了Thread,Executor,Synchronized,AtomicXXX等类型或者关键字,我们就可以充分灵活的去用我们人类更熟悉的语法定义操作底层机器基本的CPU和内存操作来完成我们的复杂应用的设计。

关于并发应用的开发Java的JDK中提供的java.util.current包里定义了很多关于上面应用的类型接口,类实现等内容,都是围绕着线程定义,线程相互关系处理,同步控制,原子操作,以及运算结果处理等内容。

其中还包括实现了锁,同步,原子操作等集合类型数据定义,从而让我们能够并行处理数据集合,我们可以从上面我说的几个方面去理解这些并发数据,集合,队列等定义的内容,千万不要不了解是什么就只是知道哪个集合适合并发,哪个不适合,哪个性能更好等,一定要知道为什么。

比如ConcurrentHashMap为什么在处理大规模数据并发时性能更好,主要是其加锁的范围是基于Hash索引的,而我们知道HashMap的每个Hash索引下面可以放置多个链表数值的。

当加锁或者进行排队只在哈希索引级别是,我们只是对整体数据的局部整体进行了锁定,而不是全部,所以其并发处理性能有高。

而对于CPU操作单元的管理,Java为我们提供了一个抽象的Executors类,并提供了常用的固定数量的线程池,单线程池,和无限线程池等多种直接可以调用来创建线程的方法,同时还提供了一些对于多线程并行执行结果处理的定义,Callable,Future等这些返回值规则。还有对于我们常见的逻辑结构实现,比如ForkJoin线程池,能够自动在一定条件下执行多线程,然后通过信号量或者闩锁来达到将多线程执行的结果统一时间和步骤的处理等。

总结

总之,这里我们从一个更概括的层次上总体描述了一下Java编程从一个应用程序到其更具体的主要组成,数据类型,逻辑执行单元,单线程和多线程,并发执行,线程池,数据集合并发同步操作等概念。只是简单的一个思路整理,可能有些无序,希望对大家对于Java编程的理解有帮助。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值