Java服务端性能优化
《Java程序性能优化》说性能优化包含五个层次:设计调优、代码调优、JVM调优、数据库调优、操作系统调优。
常用的几个代码优化方案:
使用单例
对于IO处理、数据库连接、配置文件解析加载等一些非常耗费系统资源的操作,我们必须对这些实例的创建进行限制,或者是始终使用一个公用的实例,以节约系统开销,这种情况下就需要用到单例模式。
使用Future模式
假设一个任务执行起来需要花费一些时间,为了省去不必要的等待时间,可以先获取一个“提货单”,即Future,然后继续处理别的任务,直到“货物”到达,即任务执行完得到结果,此时便可以用“提货单”进行提货,即通过Future对象得到返回值。
public class RealData implements Callable<String> {
protected String data;
public RealData(String data) {
this.data = data;
}
@Override
public String call() throws Exception {
//利用sleep方法来表示真是业务是非常缓慢的
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return data;
}
}
public class Application {
public static void main(String[] args) throws Exception {
FutureTask<String> futureTask =
new FutureTask<String>(new RealData("name"));
ExecutorService executor =
Executors.newFixedThreadPool(1); //使用线程池
//执行FutureTask,相当于上例中的client.request("name")发送请求
executor.submit(futureTask);
//这里可以用一个sleep代替对其他业务逻辑的处理
//在处理这些业务逻辑过程中,RealData也正在创建,从而充分了利用等待时间
Thread.sleep(2000);
//使用真实数据
//如果call()没有执行完成依然会等待
System.out.println("数据=" + futureTask.get());
}
}
使用线程池
合理利用线程池能够带来三个好处。第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
在 Java 5 之后,并发编程引入了一堆新的启动、调度和管理线程的API。Executor 框架便是 Java 5 中引入的,其内部使用了线程池机制,它在 java.util.cocurrent 包下,通过该框架来控制线程的启动、执行和关闭,可以简化并发编程的操作。
public class MultiThreadTest {
public static void main(String[] args) {
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("thread-%d").build();
ExecutorService executor = new ThreadPoolExecutor(2, 5, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory);
executor.execute(new Runnable() {
@Override
public void run() {
System.out.println("hello world !");
}
});
System.out.println(" ===> main Thread! " );
}
}
使用NIO
JDK自1.4起开始提供全新的I/O编程类库,简称NIO,其不但引入了全新高效的Buffer和Channel,同时,还引入了基于Selector的非阻塞 I/O机制,将多个异步的I/O操作集中到一个或几个线程当中进行处理,使用NIO代替阻塞I/O能提高程序的并发吞吐能力,降低系统的开销。
对于每一个请求,如果单独开一个线程进行相应的逻辑处理,当客户端的数据传递并不是一直进行,而是断断续续的,则相应的线程需要 I/O等待,并进行上下文切换。而使用NIO引入的Selector机制后,可以提升程序的并发效率,改善这一状况。
public class NioTest {
static public void main( String args[] ) throws Exception {
FileInputStream fin = new FileInputStream("c:\\test.txt");
// 获取通道
FileChannel fc = fin.getChannel();
// 创建缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 读取数据到缓冲区
fc.read(buffer);
buffer.flip();
while (buffer.remaining()>0) {
byte b = buffer.get();
System.out.print(((char)b));
}
fin.close();
}
}
锁优化
在并发场景中,我们的代码中经常会用到锁。存在锁,就必然存在锁的竞争,存在锁的竞争,就会消耗很多资源。那么,如何优化我们Java代码中的锁呢?主要可以从以下几个方面考虑:
- 减少锁持有时间(可以使用同步代码块来代替同步方法。这样既可以减少锁持有的时间。)
- 减少锁粒度(要在并发场景中使用Map的时候,记得使用ConcurrentHashMap来代替HashTable和HashMap。)
- 锁分离(普通锁(如syncronized)会导致读阻塞写、写也会阻塞读,同时读读与写写之间也会进行阻塞,可以想办法将读操作和写操作分离开。)
- 锁粗化(有些情况下我们希望把很多次锁的请求合并成一个请求,以降低短时间内大量锁请求、同步、释放带来的性能损耗。)
- 锁消除(锁消除是Java虚拟机在JIT编译是,通过对运行上下文的扫描,去除不可能存在共享资源竞争的锁,通过锁消除,可以节省毫无意义的请求锁时间。)
压缩传输
在进行数据传输之前,可以先将数据进行压缩,以减少网络传输的字节数,提升数据传输的速度,接收端可以将数据进行解压,以还原出传递的数据,并且,经过压缩的数据还可以节约所耗费的存储介质(磁盘或内存)的空间以及网络带宽,降低成本。当然,压缩也并不是没有开销的,数据压缩需要大量的CPU计算,并且,根据压缩算法的不同,计算的复杂度以及数据的压缩比也存在较大差异。一般情况下,需要根据不同的业务场景,选择不同的压缩算法。
缓存结果
对于相同的用户请求,如果每次都重复的查询数据库,重复的进行计算,将浪费很多的时间和资源。将计算后的结果缓存到本地内存,或者是通过分布式缓存来进行结果的缓存,可以节约宝贵的CPU计算资源,减少重复的数据库查询或者是磁盘I/O,将原本磁头的物理转动变成内存的电子运动,提高响应速度,并且线程的迅速释放也使得应用的吞吐能力得到提升
转载:
原文地址:人人都能掌握的Java服务端性能优化方案
Java服务端性能优化的更多相关文章
- 人人都能掌握的Java服务端性能优化方案
作为一个Java后端开发,我们写出的大部分代码都决定着用户的使用体验.如果我们的后端代码性能不好,那么用户在访问我们的网站时就要浪费一些时间等待服务器的响应.这就可能导致用户投诉甚至用户的流失. 关于 ...
- Web服务端性能提升实践
随着互联网的不断发展,日常生活中越来越多的需求通过网络来实现,从衣食住行到金融教育,从口袋到身份,人们无时无刻不依赖着网络,而且越来越多的人通过网络来完成自己的需求. 作为直接面对来自客户请求的Web ...
- Java 服务端入门和进阶指南
作者:谢龙 链接:https://www.zhihu.com/question/29581524/answer/44872235 来源:知乎 著作权归作者所有,转载请联系作者获得授权. 现在互联网上资 ...
- 那些年,我们见过的 Java 服务端“问题”
导读 明代著名的心学集大成者王阳明先生在<传习录>中有云: 道无精粗,人之所见有精粗.如这一间房,人初进来,只见一个大规模如此.处久,便柱壁之类,一一看得明白.再久,如柱上有些文藻,细细都 ...
- 俯瞰 Java 服务端开发
原文首发于 github ,欢迎 star . Java 服务端开发是一个非常宽广的领域,要概括其全貌,即使是几本书也讲不完,该文将会提到许多的技术及工具,但不会深入去讲解,旨在以一个俯瞰的视角去探寻 ...
- 5种kafka消费端性能优化方法
摘要:带你了解基于FusionInsight HD&MRS的5种kafka消费端性能优化方法. 本文分享自华为云社区<FusionInsight HD&MRSkafka消费端性能 ...
- Java 服务端监控方案(四. Java 篇)
http://jerrypeng.me/2014/08/08/server-side-java-monitoring-java/ 这个漫长的系列文章今天要迎来最后一篇了,也是真正与 Java 有关的部 ...
- 那些年,我们见过的 Java 服务端乱象
导读 查尔斯·狄更斯在<双城记>中写道:“这是一个最好的时代,也是一个最坏的时代.” 移动互联网的快速发展,出现了许多新机遇,很多创业者伺机而动:随着行业竞争加剧,互联网红利逐渐消失,很多 ...
- 那些年,我们见过的Java服务端乱象
导读 查尔斯·狄更斯在<双城记>中写道:“这是一个最好的时代,也是一个最坏的时代.”移动互联网的快速发展,出现了许多新机遇,很多创业者伺机而动:随着行业竞争加剧,互联网红利逐渐消失,很多创 ...
随机推荐
- mysql性能调优注意事项
1.最左原则 注意遇到> < like between失效 2.对于like 查询 遇到最左%索引无效 3.SQL性能优化目标:至少要达到range(对索引进行范围查找)级别,要求是 ...
- MP(MyBatis-Plus)实现乐观锁更新功能
实现步骤 step1:添加乐观锁拦截器 MP的其他拦截器功能可以参考官网 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { ...
- lcobucci/jwt的安装和使用
安装 composer require lcobucci/jwt 3.3 封装 <?php namespace tools\jwt; use Lcobucci\JWT\Builder; use ...
- LeetCode141-环形链表检测
题目 给定一个链表,判断链表中是否有环. 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置 ...
- oracle坚决不挂01(表,索引,视图的创建,修改,删除,查询)
考试快来了,来篇oracle干货,复习一下(挣扎一下) 废话不多说,开始写! 这篇是数据库对象的有关操作的总结! 数据库对象有熟悉的表,视图,索引,序列,同义词等(这个oracle东西真不少,小声bb ...
- .NET 调整图片尺寸(Resize)各种方法
本文中如无特别说明 .NET 指 .NET 5或者更高版本,代码同样可用于 .NET Core 前言 调整图片尺寸最常用的场景就是生成缩略图,一般为保持纵横比缩小,如果图片放大会使图片变得模糊,如果确 ...
- Spring框架之websocket源码完全解析
Spring框架之websocket源码完全解析 Spring框架从4.0版开始支持WebSocket,先简单介绍WebSocket协议(详细介绍参见"WebSocket协议中文版" ...
- 一次snapshot迁移引发的Hbase RIT(hbase2.1.0-cdh6.3.0)
1. 问题起因 通过snapshot做跨集群数据同步时,在执行拷贝脚本里没有指定所有者及所有组,导致clone时没有权限,客户端卡死.master一直报错,经过一系列操作后,导致RIT异常. 2. 异 ...
- QPinter 常用绘制图像的方法
阅读本文大概需要 3 分钟 我们在开发软件的过程中,绘制图像功能必不可少,使用 Qt 绘制图像时非常简单,只需要传递几个参数就可以实现功能,在 Qt 中绘制图像的 api有好几个 void drawI ...
- 【MySQL】1托2 ab复制 一个主机两个slave操作手册
所有实验环境全部是新建的,如果不是新建的mysql一定要备份!!! 环境:CentOS release 6.8 x64 master:192.168.25.100 slave1: 192.168.25 ...