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服务端乱象
导读 查尔斯·狄更斯在<双城记>中写道:“这是一个最好的时代,也是一个最坏的时代.”移动互联网的快速发展,出现了许多新机遇,很多创业者伺机而动:随着行业竞争加剧,互联网红利逐渐消失,很多创 ...
随机推荐
- 零基础学习qt4 第七章的第一个例子
#include <QtGui> #include "extensionDlg.h" ExtensionDlg::ExtensionDlg(QWidget *paren ...
- 多线程,线程类三种方式,线程调度,线程同步,死锁,线程间的通信,阻塞队列,wait和sleep区别?
重难点梳理 知识点梳理 学习目标 1.能够知道什么是进程什么是线程(进程和线程的概述,多进程和多线程的意义) 2.能够掌握线程常见API的使用 3.能够理解什么是线程安全问题 4.能够知道什么是锁 5 ...
- android 百度地图 团队开发及正式apk发布
百度地图开发关键是获取正确的API Key, 百度官网写的只是在你本地的机器能运行 你把AndroidManifest.xml(这里是最新的v2_4_1,API Key配置在这里) svn 提交后 ...
- 消息队列 ---常用的 MQ 中间件
目前市面上比较常用的 MQ(Message Queue,消息队列)中间件有 RabbitMQ.Kafka.RocketMQ,如果是轻量级的消息队列可以使用 Redis 提供的消息队列,其中 Redis ...
- 使用sublime text3搭建Python编辑环境
最近在工作遇到一个难题. 我所在的测试组有一套PC软件前端自动化工程,在进行自动化测试时,需要在一台古老的xp机器上运行,但这台古老的xp机器带给我诸多烦恼,特别是使用Pycharm编辑器时,我遇到了 ...
- 浅谈localStorage的使用场景和优劣势,以及sessionStorage和cookie
一.localStorage,sessionStorage,cookie的简单介绍 localStorage:仅在客户端存储不参与服务器通信,存储大小一般为5M,如果不是人为清除,那么即使是关闭浏览器 ...
- newbee-mall 开源商城新计划:秒杀功能、优惠券、对接支付宝
新项目是 newbee-mall 的升级版本,暂时就叫它 newbee-mall-plus 吧,第一阶段会开发秒杀功能.优惠券.对接支付宝这些功能,也会慢慢加入 Redis. Elastic Sear ...
- 【二分搜索树】1、二分查找法的实现 - Binary Search
简单记录 - bobo老师的玩转算法系列–玩转算法 - 二分搜索树 二叉搜索树 Binary Search Tree 查找问题 Searching Problem 查找问题是计算机中非常重要的基础问题 ...
- 【ORACLE错误】SP2-0618: Cannot find the Session Identifier. Check PLUSTRACE role is enabled
执行set autotrace traceonly的时候,报错 SQL> set autotrace traceonly SP2-0618: Cannot find the Session Id ...
- mysql—if函数
在mysql中if()函数的具体语法如下:IF(expr1,expr2,expr3),如果expr1的值为true,则返回expr2的值,如果expr1的值为false,则返回expr3的值. 开始实 ...