Java7 HotSpot (TM) VM 内存模型
本文我们来学习一下 Java7 HotSpot (TM) VM 内存模型。
JVM Architecture
我们先来了解一下 JVM 的整体架构体系,JVM 主要分三大子系统:Class Loader SubSystem、Runtime Data Area、Execution Engine 。
Class Loader SubSystemJava 的动态类加载功能由类加载器子系统处理。 它在运行时第一次引用类时加载,链接和初始化类,而不是在编译时引用。 它执行三个主要功能,如加载,链接和初始化。
Execution Engine被分配给运行时数据区域中的字节码将被执行引擎来执行。 执行引擎读取字节代码并挨个挨个执行。
本篇将重点介绍 Rumtime Date Area,至于 Class Loader SubSystem 和 Execution Engine 将放在后期的文章中去讲解。
Runtime Data AreaJava 虚拟机定义了在程序执行期间使用的各种运行时数据区域。 其中一些数据区域是随着 Java 虚拟机启动而创建,随着 Java 虚拟机退出而销毁。其他数 ...
设计模式 | 模板方法 (Template Method)
What
父类定义处理流程的框架,子类实现流程中各个功能的具体细节。
设计原则:Do not call me, I will call you.
HowUML 图
代码
以我们日常工作的日程安排为例
定义父类 Worker,里面定义了框架流程方法 dailyRountine:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778package one.wangwei.designpatterns.templatemethod;import lombok.extern.slf4j.Slf4j;@Slf4jpublic abstract class Worker { /** * 每日日程安排 */ public void dailyRountine() { String name = ...
设计模式 | 抽象工厂 (Abstract Factory)
定义抽象工厂是一种创造性设计模式,可让您生成相关对象的家族,而无需指定具体的类。
问题想象一下,你正在创建一个家具店的模拟器。 你的代码包括:
家庭相关的产品:Chair + Sofa + CoffeeTable.
这些家具在风格上会存在一些变化,比如:IKEA (宜家),VictorianStyle (维多利亚风格),ArtDeco (艺术装饰) 等等。
您需要一种方法来创建各个家具对象,以便它们与同一系列的其他家具对象在风格上相匹配。否则, 客户在收到不匹配的家具时会感到非常沮丧。
此外,在向程序添加新产品或产品系列时,您不希望更改现有的代码。 家具供应商经常更新他们的产品目录,我们并不想每次都去更改核心代码。
方案抽象工厂 模式建议要做的第一件事情就是浏览一下所有的不同种类的产品,并且强制统一它们的变种,以便让它们实现相同的接口。例如,所有不同种类的的 Chair 都要实现 Chair 接口;所有的 coffee table 必须实现 CoffeeTable 接口,等等。
第二步就是创建 AbstractFactory,这是一个基础接口,它声明创建构成产品系列的所 ...
设计模式 | 工厂方法 (Factory Method)
定义工厂方法是一种创建式设计模式,它提供了用于在超类中创建对象的接口,但允许子类改变将要创建的对象的类型。
问题想象一下,你正在创建一个物流管理应用程序。 您的应用程序的第一个版本只能处理卡车运输,因此大部分代码都在 Truck 类中。
过了一段时间,您的应用程序变得非常流行,以至于您会收到大量包含海运的请求。
好消息,对吧?! 但是代码如何? 它看起来大部分代码都与 Truck 类相关联。 添加船只需要更改整个代码库。 此外,如果您决定为应用程序添加其他类型的交通工具,则可能需要再次进行所有这些更改。
你最终会遇到一些令人讨厌的代码,它们会根据传输对象的类别选择行为。
方案工厂方法设计模式建议使用一个叫” 工厂” 的方法来替代直接通过 new 来创建对象。构造函数调用应该在该方法内移动。 工厂方法返回的对象通常被称为 “产品”。
咋一看上去,这一举动貌似毫无意义。但是你可以在子类中重写工厂方法,并且改变将要创建的类对象。让我们看看它是如何工作的:
当然,有一些小小的限制:所有的产品都必须有一个通用的接口(比如 Transport)。 基类中的 Factory 方法应该返 ...
线程 IO 模型介绍
本文转载自:https://juejin.im/post/5b8f23b96fb9a019ec6a133d
前面,我们了解到了服务器如何基于 I/O 模型管理连接,获取输入数据,下面介绍基于进程 / 线程模型,服务器如何处理请求。
值得说明的是,具体选择线程还是进程,更多是与平台及编程语言相关,例如 C 语言使用线程和进程都可以 (例如 Nginx 使用进程,Memcached 使用线程),Java 语言一般使用线程 (例如 Netty),为了描述方便,下面都使用线程来进程描述。
传统阻塞 I/O 服务模型![Blocking IO Server](https://img.i7years.com/blog/Blocking IO Server.png)
特点
采用阻塞式 I/O 模型获取输入数据
每个连接都需要独立的线程完成数据输入,业务处理,数据返回的完整操作
存在问题
当并发数较大时,需要创建大量线程来处理连接,系统资源占用较大
连接建立后,如果当前线程暂时没有数据可读,则线程就阻塞在 read 操作上,造成线程资源浪费
Reactor 模式针对传统阻塞 I ...
Unix IO 模型介绍
随着互联网的发展,面对海量用户的高并发业务场景,传统的阻塞式的服务端架构模式已经无能为力,C10K 问题越来越凸显,需要一种新型的 IO 模型来解决此类问题。本文我们先来一起学习一下几种常见的 I/O 模型。
本文讨论的背景是 Linux 环境下的 Network IO
基本概念用户空间与内核空间现在操作系统都是采用虚拟存储器,那么对 32 位操作系统而言,它的寻址空间(虚拟存储空间)为 4G(2 的 32 次方)。操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。为了保证用户进程不能直接操作内核(kernel),保证内核的安全,操心系统将虚拟空间划分为两部分,一部分为内核空间,一部分为用户空间。针对 linux 操作系统而言,将最高的 1G 字节(从虚拟地址 0xC0000000 到 0xFFFFFFFF),供内核使用,称为内核空间,而将较低的 3G 字节(从虚拟地址 0x00000000 到 0xBFFFFFFF),供各个进程使用,称为用户空间。
网络请求处理流程服务端处理网络请求的大致流程为:
主要处理步骤如下 ...
Java IO vs NIO
前面我们介绍了一系列的 NIO Channel 的使用,发现它与标准的 IO 有很大的不同,本篇我们就来总结一下 NIO 与 IO 之间的差异。
主要区别对比如下:
IO
NIO
面向流 (Stream)
面向缓冲 (Buffer)
阻塞 IO (Blocking IO)
非阻塞 IO (Non Blocking IO)
\
选择器 (Selectors)
流 vs 缓冲区Java NIO 和 IO 之间的第一个重要区别是 IO 是面向流的,而 NIO 是面向缓冲区的。
IO 以面向流为主,意味着你可以从流中一次性读取一个或多个字节。如何操作读取到的字节取决于你自己。这些流中的字节没有做任何缓存。此外,你无法在流中的数据做前后移动操作。如果你想要对读取到数据做前后移动操作,则必须将其缓存到 Buffer 中。
Java NIO 的面向缓冲区的方法略有不同。数据读入缓冲区,然后在处理该缓冲区。 你可以根据你的需要在缓冲区中做前后移动操作。这样可以提高处理数据时的灵活性。不过,在处理数据之前,还需要检查缓冲区是否包含了完整的数据,并且,要确保缓 ...
Java NIO2 Asynchronous Channel APIs
前面 我们介绍了 NIO 中一系列同步非阻塞 API 的用法。在 Java 7 中引入了 NIO 的改进版 NIO 2,NIO 2 也就是我们常说的 AIO,它是异步非阻塞的 IO 方式。
AIO 的核心概念就是发起非阻塞方式的 I/O 操作,立即响应,却不立即返回结果,当 I/O 操作完成时通知。
Asynchronous Channel APIs 工作原理从 Java 7 开始,java.nio.channel 包中新增加 4 个异步 Channel:
AsynchronousFileChannel
AsynchronousSocketChannel
AsynchronousServerSocketChannel
AsynchronousDatagramChannel
从名字上,你可以感受到它们与同步非阻塞 Channel API 在风格上有些类似。而且,同步非阻塞 Channel API 中的诸多用法在新的异步非阻塞 Channel 中依然适用,不同之处在于,新的异步 Channel 能够允许一些操作异步执行。
当操作启动时,异步通道 API 为我们提供了两种用于 ...
Java NIO Pipe
Java NIO Pipe 是两个线程之间的单向数据连接。 Pipe (管道) 具有 source channel (源通道) 和 sink channel (接收器通道) 。 你将数据写入接收器通道,然后可以从源通道读取该数据。
示意图如下:
基本用法创建 Pipe直接调用 open() 方法创建 Pipe. 如下:
1Pipe pipe = Pipe.open();
写入 Pipe数据先要写入到 sink channel,因此先要获取 sink channel.
1Pipe.SinkChannel sinkChannel = pipe.sink();
写入 sinkChannel (),如下:
1234567891011String newData = "New String to write to file..." + System.currentTimeMillis();ByteBuffer buf = ByteBuffer.allocate(48);buf.clear();buf.put(newData.getBytes());buf.flip();whil ...
Java NIO ServerSocketChannel、SocketChannel、DatagramChannel
前面 我们介绍了 FileChannel,本篇我们来一起学习 SocketChannel, ServerSocketChannel 与 DatagramChannel。
ServerSocketChannelJava NIO ServerSocketChannel 是用于监听 TCP 端口连接的通道,与 Java 标准 IO 中的 ServerSocket 一样。ServerSocketChannel 位于 java.nio.channels 包下。
例如:
12345678ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.socket().bind(new InetSocketAddress(9999));while(true){ SocketChannel socketChannel = serverSocketChannel.accept(); //do something with socketChannel...}
打开 S ...