Tomcat调优和JVM优化
Tomcat调优和JVM优化Tomcat本身优化工作方式选择
为了提升性能,首先就要对代码进行动静分离,让 Tomcat 只负责 jsp 文件的解析工作。如采用 Apache 和 Tomcat 的整合方式,他们之间的连接方案有三种选择,JK、http_proxy 和 ajp_proxy。相对于 JK 的连接方式,后两种在配置上比较简单的,灵活性方面也一点都不逊色。但就稳定性而言不像JK 这样久经考验,所以建议采用 JK 的连接方式。
Connector 连接器的配置
之前文件介绍过的 Tomcat 连接器的三种方式: bio、nio 和 apr,三种方式性能差别很大,apr 的性能最优, bio 的性能最差。而 Tomcat 7 使用的 Connector 默认就启用的 Apr 协议,但需要系统安装 Apr 库,否则就会使用 bio 方式。
配置文件设置常见异常-java.lang.OutOfMemoryError: Java heap space
JVM堆的设置是指java程序运行过程中JVM可以调配使用的内存空间的设置.JVM在启动的时候会自动设置Heap size的值,其 ...
基于Netty实现聊天室
基于Netty实现聊天室Netty简介
Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。
也就是说,Netty 是一个基于NIO的客户,服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用。Netty相当简化和流线化了网络应用的编程开发过程。
Netty更多详细介绍
Server端12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061package chatroom;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.*;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel. ...
NIO学习笔记及实现简单聊天室
NIO学习笔记及实现简单聊天室NIO简介
Java NIO(New IO) 是从Java 1.4版本开始引入的 一个新的IO API,可以替代标准的Java IO API。 NIO与原来的IO有同样的作用和目的,但是使用 的方式完全不同, NIO支持面向缓冲区的、基于 通道的IO操作。 NIO将以更加高效的方式进行文 件的读写操作
NIO与IO主要区别
NIO通道与缓冲区
通道(Channel)和缓冲区 (Buffer)。通道表示打开到 IO 设备(例如:文件、 套接字)的连接。若需要使用 NIO 系统,需要获取 用于连接 IO 设备的通道以及用于容纳数据的缓冲 区。然后操作缓冲区,对数据进行处理 。Java NIO 中的 Buffer 主要用于与 NIO 通道进行 交互,数据是从通道读入缓冲区,从缓冲区写 入通道中的。
Buffer
Buffer 就像一个数组,可以保存多个相同类型的数据。根 据数据类型不同(boolean 除外) ,有以下 Buffer 常用子类: ByteBuffer CharBuffer ShortBuffer IntBuff ...
Docker部署Spring Boot应用
Docker部署Spring Boot应用
Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机)、bare metal、OpenStack 集群和其他的基础应用平台。 使用Docker我们可以很方便的部署Spring Boot应用。
首先构建一个简单的 Spring Boot 项目,然后给项目添加 Docker 支持,最后对项目进行部署
Spring Boot 项目
在pom.xml文件中添加web和测试依赖
1234567891011<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId ...
ForkJoinPool
ForkJoinPoolFork/Join框架
Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。我们再通过Fork和Join这两个单词来理解下Fork/Join框架,Fork就是把一个大任务切分为若干子任务并行的执行,Join就是合并这些子任务的执行结果,最后得到这个大任务的结果。比如计算1+2+。。+10000,可以分割成10个子任务,每个子任务分别对1000个数进行求和,最终汇总这10个子任务的结果。
使用方法:创建了ForkJoinPool实例之后,就可以调用ForkJoinPool的submit(ForkJoinTask task) 或invoke(ForkJoinTask task)方法来执行指定任务了。
其中ForkJoinTask代表一个可以并行、合并的任务。ForkJoinTask是一个抽象类,它还有两个抽象子类:RecusiveAction和RecusiveTask。其中RecusiveTask代表有返回值的任务,而RecusiveAction代表没有返回值的 ...
模拟CAS
模拟CASCAS
CAS是一种无锁的非阻塞算法,全称为:Compare-and-swap(比较并交换)算法保证数据的原子性,CAS是硬件对于并发操作共享数据的支持,包含三个操作数,大致思路是:先比较目标对象现值是否和旧值一致,如果一致,则更新对象为新值;如果不一致,则表明对象已经被其他线程修改,直接返回.
1234567891011121314151617181920212223242526272829303132333435363738394041/** * @Author: Usher * @Description: * 模拟CAS */public class TestCompareAndSwap { public static void main(String[] args) { final CompareAndSwap compareAndSwap = new CompareAndSwap(); for(int i = 0;i < 10;i++){ new Thread(new Ru ...
写一个死锁程序
写一个死锁程序什么是死锁?
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
死锁产生的原因?
〈1〉互斥条件。即某个资源在一段时间内只能由一个进程占有,不能同时被两个或两个以上的进程占有。这种独占资源如CD-ROM驱动器,打印机等等,必须在占有该资源的进程主动释放它之后,其它进程才能占有该资源。这是由资源本身的属性所决定的。如独木桥就是一种独占资源,两方的人不能同时过桥。
〈2〉不可抢占条件。进程所获得的资源在未使用完毕之前,资源申请者不能强行地从资源占有者手中夺取资源,而只能由该资源的占有者进程自行释放。如过独木桥的人不能强迫对方后退,也不能非法地将对方推下桥,必须是桥上的人自己过桥后空出桥面(即主动释放占有资源),对方的人才能过桥。
〈3〉占有且申请条件。进程至少已经占有一个资源,但又申请新的资源;由于该资源已被另外进程占有,此时该进程阻塞;但是,它在等待新资源之时,仍继续占用已占有的资源。还以过独木桥 ...
浏览器的一个请求从发送到返回
浏览器的一个请求从发送到返回浏览器的一个请求从发送到返回1、先从网络模型层面:client (浏览器)与server 通过 http 协议通讯,http 协议属于应用层协议,http 基于 tcp 协议,所以 client 与 server 主要通过socket 进行通讯;
而 tcp属于传输层协议、如果走 https 还需要会话层 TLS、SSL 等协议; 传输层之下网络层,这里主要是路由协议 OSPF等进行路由转发之类的。再向下数据链路层主要是 ARP、RARP 协议完成 IP 和 Mac 地址互解析,再向下到最底层物理层基本就是 IEEE 802.X等协议进行数据比特流转成高低电平的的一些定义等等;
当浏览器发出请求,首先进行数据封包,然后数据链路层解析IP 与 mac 地址的映射,然后上层网路层进行路由查表路由,通过应用层 DNS 协议得到目标地址对应的 IP ,在这里进行 n 跳的路由寻路;而传输层tcp 协议可以说下比较经典的三次握手、四次分手的过程和状态机,这里放个图可以作为参考:
2、应用层方面:数据交换主要通过 http协议, http 协议是无状态协议,这里可以谈一 ...
LRU缓存实现-LinkedHashMap
LRU缓存实现-LinkedHashMap
LRU是Least Recently Used 的缩写,翻译过来就是“最近最少使用”.
LRU缓存的思想
固定缓存大小,需要给缓存分配一个固定的大小。
每次读取缓存都会改变缓存的使用时间,将缓存的存在时间重新刷新。
需要在缓存满了后,将最近最久未使用的缓存删除,再添加最新的缓存。
按照LinkedHashMap自身已经实现了顺序存储,默认情况下是按照元素的添加顺序存储,也可以启用按照访问顺序存储,传入的第三个参数accessOrder为true的时候,就按访问顺序对LinkedHashMap排序,为false的时候就按插入顺序,默认是为false的。
当把accessOrder设置为true后,就可以将最近访问的元素置于最前面,这样就可以满足上述的第二点。即最近读取的数据放在最前面,最早读取的数据放在最后面,然后它还有一个判断是否删除最老数据的方法,默认是返回false,即不删除数据,我们使用LinkedHashMap实现LRU缓存的方法就是对LinkedHashMap实现简单的扩展,扩展方式有两种,一种是inheritance,采用 ...
生产者-消费者问题-BlockingQueue实现
生产者-消费者问题-BlockingQueue实现
生产者-消费者(producer-consumer)问题,也称作有界缓冲区(bounded-buffer)问题,两个进程共享一个公共的固定大小的缓冲区。其中一个是生产者,用于将消息放入缓冲区;另外一个是消费者,用于从缓冲区中取出消息。问题出现在当缓冲区已经满了,而此时生产者还想向其中放入一个新的数据项的情形,其解决方法是让生产者此时进行休眠,等待消费者从缓冲区中取走了一个或者多个数据后再去唤醒它。同样地,当缓冲区已经空了,而消费者还想去取消息,此时也可以让消费者进行休眠,等待生产者放入一个或者多个数据时再唤醒它。
BlockingQueue
阻塞队列,顾名思义,首先它是一个队列,而一个队列在数据结构中所起的作用大致如下图所示:从上图我们可以很清楚看到,通过一个共享的队列,可以使得数据由队列的一端输入,从另外一端输出;常用的队列主要有以下两种:(当然通过不同的实现方式,还可以延伸出很多不同类型的队列,DelayQueue就是其中的一种) 先进先出(FIFO):先插入的队列的元素也最先出队列,类似于排队的功能。从某种程度上来说这种队列 ...