JVM,面向对象编程思想,多线程编程,I/O多路复用

一.JVM内存模型:

1.java内存主要由五部分组成,分别四:程序计数器,jvm栈,本地方法栈,堆以及方法区:

    1)程序计数器:线程私有,生命周期随着线程的创建而创建,随着线程的销毁,占用很少的内存空间,不会出现内存溢出。作用是标识下一条需要执行的指令的位置,分支,循环,跳转,异常处理,线程恢复等基础功能都是依赖程序计数器完成的。

  2)jvm栈:java方法运行时分配的内存,jvm栈会为每个即将运行的java方法分配一个交帧栈的区域,用来存储方法运行时所需的信息,信息主要包括局部变量表,操作数栈,动态链接以及方法出口信息,线程私有的,生命周期随着线程的创建而创建,随着线程的销毁。

3)本地方法栈:功能与jvm栈类型,只不过是java本地方法(native关键字修饰的方法,通常比较底层,用于链接操作系统与java)时分配的内存模型。

4)堆:垃圾回收的主要内存,用来存放实例化的对象以及数组等。

2.什么是jvm?
   1)jvm是一种用于计算机设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的。

2)jvm包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收器和一个存储方法域。

3)jvm屏蔽了与具体操作系统平台相关的信息,使java程序只需要生成在java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修饰地运行。

3.JVM原理:

1)jvm是java的核心和基础,在java编译器和OS平台之间的虚拟处理器,可在上面执行字节码程序。

2)java编译器只要面向JVM,生成jvm能理解的字节码文件,java源文件经编译成字节码程序,通过jvm将每条指令翻译成不同的机器码,通过特定平台运行。


二.面向对象的编程思想:

1.什么是面向对象:

面向对相关思想将客观世界中的事物描述为对象,并通过抽象思维方法将需要解决的实际问题分解为人民易于理解的对象模型,然后通过这些对象模型俩构建应用程序的组成;

2.面向对象的概念:

对象,类,封装,继承,多态

对象:客观具体存在的事物,比如这个人,这个桌子,由属性和行为组成;

类:对大量对象共性的抽象,是对客观事物的抽象,也由属性和行为组成;

3.四大基本特征:

1).抽象:提取现实世界中某些事物的关键特性,为该事物建模的过程,得到的模型中一般包含属性(数据)和操作(行为);

2).封装:把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏;

3).继承:可以使用现有类的所有功能,并在无需重新编写原理的类的情况下对这些功能进行扩展。

4).多态:允许将子类类型的引用赋值给父类类型的,将父对象设置成为和一个或更多的她的子对象相等,赋值之后,父对象就可以根据当前赋值给她的子对象的特性以不同的方式运作。

封装可以隐藏实现的细节,使得代码模块化;

继承可以扩展已存在的代码模块(类);为了实现代码重用;

多态则是为了实现接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。

4.七大设计原则: 

1.开闭原则:就是在不修改原有代码的前提下给程序扩展功能,增加了程序的可扩展性。

2.单一职责原则:一个类只允许有一个职责,即只有一个导致该类变更的原因。

3.依赖倒置原则:依赖抽象而不是依赖实现,高层模块不能依赖底层模块。

4.接口分离原则:多个特定的客户端接口要好于一个通用性的总接口;避免用一个接口里面包含不同职责的方法,接口责任划分更加明确。

5.迪米特法则:一个对象应该对尽可能少的对象有接触,只接触那些真正需要接触的对象

6.里氏替换原则:所有引用基类的地方必须能透明地使用子类的对象,而程序执行效果不变。可以检测继承使用的正确性。

7.合成复用原则:尽量使用合成/聚合的方式,而不是使用继承。

三.多线程编程:

1.进程与线程:

 1)进程:进程是程序的一次动态执行过程,它经历了从代码加载,执行,到执行完毕的一个完整过程;同时也是并发执行的程序在执行过程中分配和管理资源的基本单位,竞争计算机系统资源的基本单位。

2)线程:线程可以理解为进程中的执行的一段程序片段,是进程的一个执行单元,是进程内可调度实体,是比进程更小的独立运行的基本单位,线程也被称为轻量级进程。

2.为什么会有线程:

每个进程都有自己的地址空间,即进程空间,在网络或多用户换机下,一个服务器通常需要接收大量不确定数量用户的并发请求,为每一个请求都创建一个进程显然还是不行的,即使多进程可提高硬件资源的利用率,但是进程的启动和销毁需要消耗大量的系统性能,从而导致程序的执行性能下降。所以为了进一步提升并发操作的处理能力,在进程的基础上又划分了多线程概念。

总之:一个程序至少一个进程,一个进程至少一个线程。

3.多线程运行状态:

(1)创建状态:实现Runnable接口和继承Thread类创建一个线程对象后,该线程对象处于创建状态,此时它已经有了内存空间和其他资源,但他还是处于不可以运行的。

(2)就绪状态:新建线程对象后,调用该线程的start方法启动该线程,启动后,进入线程队列排队,由CPU调度服务。

(3)运行状态:就绪状态的线程获得处理器的资源时,线程就进入了运行状态,此时将自动调用run方法。

(4)阻塞状态:正在运行的线程在某些特殊情况下,如:当前线程调用sleep,suspend,wait等方法时,运行在当前线程里的其他线程调用join方法时,以及等待用户输入的时候,只有当引起阻塞原因消失后,线程才能进入就绪状态。

(5)终止状态:当线程run方法运行结束后,或者主线程的main()方法结束后,线程才能处于终止状态,线程一旦死亡就不能复生。

4.多线程常用的操作方法:

(1)线程的命名与取得:线程是不确定的运行转态,名称就是线程的主要标记。因此,需要注意的是,对于线程的名字一定要在启动之前设置进程名称,不建议对已经启动的线程,进行更改名称,或者为不同线程设置重名。

(2)线程休眠方法:sleep方法定义在java.lang.Thread中,由Thread.sleep()调用实现。其作用是需要暂缓线程的执行速度,则可以让当前线程休眠,即当前线程从“运行状态”进入到“阻塞状态”。sleep方法会指定休眠时间,线程休眠的时间会大于或等于该休眠时间,该线程会被唤醒,此时它会由“阻塞状态”变成“就绪状态”,然后等待CPU的调度执行。

(3)线程中断方法:interrupt方法定义在java.lang.Thread中,由Thread.interrupt()调用实现。该方法将会设置该线程的中断状态位,即设置为true,中断的结果线程是终止状态位,即为true,中断的结果线程是终止状态,还是阻塞状态或是就绪运行至下一步,就取决于该线程本身。线程会不时地检测这个中断标示位,以判断线程是否应该被中断(即中断标示值是否为true)。它并不像stop方法那样会中断一个正在运行的线程。

(4)线程强制执行:join方法定义在java.lang.Thread中,由Thread.join()调用实现。多线程启动后会交替进行资源抢占和线程体执行,如果此时某些线程异常重要,也就是说这个对象需要优先执行完成,则可以设置为线程强制执行,待其完成后其它线程继续执行。

(5)线程让步:yield方法定义在java.lang.Thread中,由Thread.yield()调用实现。多线程在彼此交替执行的时候往往需要进行资源的轮流抢占,如果某些不是很重要的线程抢占到资源但是又不急于执行时,就可以将当前的资源暂时让步出去,交给其他资源先执行。但是,因为yeild是将线程由“运行状态”转别为“就绪状态”,这样并不能保证在当前线程调用yield方法之后,其它具有相同优先级的线程就一定能获得执行权,也有可能是当前线程又进入到“运行状态”继续运行,因为还是要依靠CPU调用才可以。

(6)线程优先级:所有创造的线程都是子线程,所有的子线程在启动时都会保持同样的优先级权限,但是如果现在某些重要的线程希望可以优先抢占到资源并且先执行,就可以修改优先级权限来实现。

需要理解的是:优先级用从1到10的范围的整数指定。10表示最高优先级,1表示最低优先级,5是普通优先级,也就是默认优先级。

优先级相对最高的线程在执行时被寄予优先权限。但是不能保证线程在启动时就进入运行状态。

优先级越高越有可能先执行。
 

5.线程同步和锁死;这样会导致了一个问题:在某一时刻,这一份资源在某一个线程发生改变时,其他线程正在执行的操作也会受到其影响。

(1)线程同步:解决数据共享问题必须使用同步,所谓的同步就是指多个线程在同一个时间段内只能有一个线程执行指定的代码,其他线程要等待此线程完成之后才可以继续进行执行,在Java中提供有synchronized关键字以实现同步处理,同步的关键是要为代码加上“锁”。

(2)线程死锁:所谓死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们将都无法推进下去,死锁是在多线程开发中较为常见的一种问题,过多的同步就有可能出现死锁。

6.后台守护线程:java中的线程分为两类,用户线程和守护线程。守护线程是一种运行在后台的线程服务线程,当用户线程存在时,守护线程可以同时存在,但是,当用户线程不存在时,守护线程会全部消失。

在主线程关闭后无需手动关闭守护线程,因为会自动关闭,避免了麻烦,java垃圾回收线程就是一个典型的疏忽线程,简单粗暴地可以理解为所有为线程服务而不涉及资源的线程都能设置成为守护线程。

7.线程池:

(1)线程池的概念:

容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程的操作,无序反复创建线程而消耗过多的资源。

(2)为什么要引入线程池?

如果并发的线程数量过多,并且每个线程都是执行一个时间很短的任务就结束,这样频繁的创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要消耗时间,线程也属于宝贵的系统资源,因此,线程池就是为了能使线程可以复用而创建的。

(3)线程池的好处?

a.降低资源的消耗,减少创建和销毁线程的次数,每个工作线程都可以被重复使用,可执行多个任务。

b.提高响应速度,不需要频繁地创建线程,如果有线程可以直接使用,避免了系统僵死

c.提高线程的可管理性

四.I/O多路复用:

1.一个进程虽然任一时刻只能处理一个请求,但是处理每个请求的时间时,耗时控制在1毫秒以内,这样1秒内就可以处理上千个请求,把时间拉长来看,多个请求复用了一个进程,这就是多路复用,这种思想很类似于一个CPU并发多个进程,所以也叫做时分多路复用。

2.我们熟悉的select/poll/epoll内核提供给用户态的多路复用系统调用,进程可以通过一个系统调用函数从内核中获取多个实践。

3.select/poll/epoll是如何获取网络实践的呢?在获取事件时,先把所有连接(文件描述符)传给内核,再由内核返回产生了事件的连接,然后再用户态中再处理这些连接对应的请求即可。

4.最基础的TCP的Socket编程,它是阻塞I/O模型,基本上只能一对一通信,那为了服务更多的客户端,我们需要改进网络I/O模型。

比较传统的方式是使用多进程/线程模型,每来一个客户端连接,就分配一个进程/线程,然后后续的读写都在对应的进程/线程,然后后续的读写都对应的进程/线程,这种方式处理100个客户端没有问题,但是当客户端增大到10000个时,10000个进程/线程的调度,上下文切换以及他们占用的内存,都会成为瓶颈。

为了解决上面这个问题,就出现为了解决上面这个问题,就出现了 I/O 的多路复用,可以只在一个进程里处理多个文件的 I/O,

Linux 下有三种提供 I/O 多路复用的 API,分别是: select、poll、epoll。

select 和 poll 并没有本质区别,它们内部都是使用「线性结构」来存储进程关注的 Socket 集合。

在使用的时候,首先需要把关注的 Socket 集合通过 select/poll 系统调用从用户态拷贝到内核态,然后由内核检测事件,当有网络事件产生时,内核需要遍历进程关注 Socket 集合,找到对应的 Socket,并设置其状态为可读/可写,然后把整个 Socket 集合从内核态拷贝到用户态,用户态还要继续遍历整个 Socket 集合找到可读/可写的 Socket,然后对其处理。

很明显发现,select 和 poll 的缺陷在于,当客户端越多,也就是 Socket 集合越大,Socket 集合的遍历和拷贝会带来很大的开销,因此也很难应对 C10K。

epoll 是解决 C10K 问题的利器,通过两个方面解决了 select/poll 的问题。

epoll 在内核里使用「红黑树」来关注进程所有待检测的 Socket,红黑树是个高效的数据结构,增删查一般时间复杂度是 O(logn),通过对这棵黑红树的管理,不需要像 select/poll 在每次操作时都传入整个 Socket 集合,减少了内核和用户空间大量的数据拷贝和内存分配。

epoll 使用事件驱动的机制,内核里维护了一个「链表」来记录就绪事件,只将有事件发生的 Socket 集合传递给应用程序,不需要像 select/poll 那样轮询扫描整个集合(包含有和无事件的 Socket ),大大提高了检测的效率。

而且,epoll 支持边缘触发和水平触发的方式,而 select/poll 只支持水平触发,一般而言,边缘触发的方式会比水平触发的效率高

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小雯洁洁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值