人人都能掌握的Java服务端性能优化方案

转载自 人人都能掌握的Java服务端性能优化方案

作为一个Java后端开发,我们写出的大部分代码都决定着用户的使用体验。如果我们的代码性能不好,那么用户在访问我们的网站时就要浪费一些时间等待服务器的响应。这就可能导致用户投诉甚至用户的流失。

关于性能优化是一个很大的话题。《Java程序性能优化》说性能优化包含五个层次:设计调优、代码调优、JVM调优、数据库调优、操作系统调优等。而每一个层次又包含很多方法论和最佳实践。本文不想大而广的概述这些内容。只是举几个常用的Java代码优化方案,读者看完之后可以真正的实践到自己代码中的方案。

使用单例

对于IO处理、数据库连接、配置文件解析加载等一些非常耗费系统资源的操作,我们必须对这些实例的创建进行限制,或者是始终使用一个公用的实例,以节约系统开销,这种情况下就需要用到单例模式。

public class Singleton {  
   private volatile static Singleton singleton;  
   private Singleton (){}  
   public static Singleton getSingleton() {  
   if (singleton == null) {  
       synchronized (Singleton.class) {  
       if (singleton == null) {  
           singleton = new Singleton();  
       }  
       }  
   }  
   return singleton;  
   }  
}

单例模式有很多种写法,我的公众号也推送过多篇和单例相关的文章:

单例模式的七种写法

设计模式(二)——单例模式

设计模式(三)——JDK中的那些单例

不使用synchronized和lock,如何实现一个线程安全的单例?

不使用synchronized和lock,如何实现一个线程安全的单例?(二)

深度解析单例与序列化之间的爱恨情仇~

使用线程池

合理利用线程池能够带来三个好处。

第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。

第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

在 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(2560L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory);
      executor.execute(new Runnable() {
          @Override
          public void run(
{
             System.out.println("hello world !");
          }
      });
      System.out.println(" ===> main Thread! " );
  }
}
使用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());  
   }  
}
使用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,将原本磁头的物理转动变成内存的电子运动,提高响应速度,并且线程的迅速释放也使得应用的吞吐能力得到提升。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329871.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python模板模式_python-模板方法模式

说明&#xff1a; 模板方法模式时行为模式中比较简单的设计模式之一。模板方法关注这样的一类行为&#xff1a;该类行为在执行过程中拥有大致相同的动作次序&#xff0c;只是动作在实现的具体细节上有所差异。例如&#xff1a;泡茶和泡咖啡&#xff0c;泡茶&#xff1a;把水煮沸…

nacos启动失败:org.springframework.boot.web.server.WebServerExceptio

准备环境 系统环境: windows nacos: 2.0.0-BETA 错误信息 org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat 配置文件…

post使用form-data和x-www-form-urlencoded的本质区别

转自&#xff1a; post使用form-data和x-www-form-urlencoded的本质区别_null-CSDN博客一是数据包格式的区别&#xff0c;二是数据包中非ANSCII字符怎么编码&#xff0c;是百分号转码发送还是直接发送一、application/x-www-form-urlencoded1、它是post的默认格式&#xff0c;…

使用Nancy打造TaskManager2.0管理系统

上一篇开源任务管理平台TaskManager介绍发布后&#xff0c;有网友联系我看看能不能做个后台管理界面&#xff0c;方便管理系统中所有的任务。由于时间和技术问题1.0版本的时候&#xff0c;新增了一个3分钟读取配置文件动态修改任务的功能&#xff0c;不过总体来说还是不直观&am…

Java对象的序列化与反序列化

转载自 Java对象的序列化与反序列化 序列化与反序列化 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。一般将一个对象存储至一个储存媒介&#xff0c;例如档案或是记亿体缓冲等。在网络传输过程中&#xff0c;可以是字节或是XML等格式。而字节的…

网站能拿到其他网站的cookie_网站能给公司带来哪些好处?

事实上&#xff0c;许多企业仍在努力建立一个网站&#xff0c;因为如果它建立起来&#xff0c;它需要一笔钱和其他费用。但此时客户业务不太好&#xff0c;企业客户需要考虑很多问题&#xff0c;但创建网站的企业已经尝到了甜头。其实有些朋友可能会有一些偏差。例如&#xff0…

笨办法学习@ConditionalOnProperty 烧脑配置记录

前言 今天继续学习springboot时&#xff0c;一不小心就被ConditionalOnProperty注解的配置真假搞得我真的变得真真假假了。。&#xff08;此为真&#xff0c;彼为假&#xff0c;到底你是真还是你是假&#xff0c;晕了晕了。。。&#xff09; 本片主要记录一下注解的真假情况 …

javaI/O流小结

【README】 1.本文总结java IO读取或写入数据的方式和相关类说明&#xff1b; 2.java IO建立在流之上的。输入流读取数据&#xff0c;输出流写入数据&#xff1b; 3.过滤器流-filter stream&#xff0c;可以串连&#xff08;修饰&#xff09;到输入流和输出流上&#xff1b;…

送给微软中文.NET社区的一份礼物,.NET FM

自报家门 大家好&#xff0c;我是.NET FM。做为一档专业而轻松的播客节目&#xff0c;在今后的日子里&#xff0c;我将为你奉上有关.NET和微软公司其他技术的新鲜资讯&#xff08;偷偷讲下&#xff0c;还有各种八卦哦&#xff09;。 Lex Li的回忆 认识吕鹏同学真的是非常偶然…

你真的以为你了解Java的序列化了吗

转载自 你真的以为你了解Java的序列化了吗 上一篇文章《Java对象的序列化与反序列化》中&#xff0c;简单介绍了Java中对象的序列化和反序列化的一些基础知识。看文那篇文章后&#xff0c;有小伙伴留言说&#xff1a;我终于了解了Java的序列化了。我只想说&#xff1a;小伙子&a…

SpringBoot配置mybatis-mysql数据源

前言 学习SpringBoot整合mybatis mysql配置&#xff0c;首先需要了解什么是ORM(对象映射关系)框架&#xff0c;ORM&#xff08;Object Relational Mapping&#xff09;对象关系映射&#xff0c;是 一种为了解决面向对象与关系型数据库不匹配而出现的技术&#xff0c;使开发者…

编程猜单词游戏python_Python实现简单的猜单词小游戏

本文实例为大家分享了Python实现猜单词小游戏的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下 思路 1、一个words列表里存放若干的单词&#xff0c;例如&#xff1a;["extends", "private", "static", "public"]2、在words…

java URL和URI

【README】 本文阐述了 URL&#xff0c; URI&#xff0c;以及对应的java类的api&#xff1b; 1.URI&#xff0c;统一资源标识符&#xff0c;标识互联网上的某个网络资源&#xff0c;标识方式如 名称&#xff0c;位置等&#xff1b;就像人的标识一样&#xff0c;可以通过身份证…

HoloLens开发手记-全息Hologram

全息 Hologram HoloLens使我们可以通过周边世界的光线和声音来创建全息场景和物体&#xff0c;使得它们像真实物体那样。全息场景能够响应你的凝视、手势和语音指令&#xff0c;同时还会和你周边世界的表面交互。借助全息场景&#xff0c;你可以在周边世界创建数码物体。 class…

全网把Map中的hash()分析的最透彻的文章,别无二家。

转载自 全网把Map中的hash()分析的最透彻的文章&#xff0c;别无二家。你知道HashMap中hash方法的具体实现吗&#xff1f; 你知道HashTable、ConcurrentHashMap中hash方法的实现以及原因吗&#xff1f; 你知道为什么要这么实现吗&#xff1f; 你知道为什么JDK 7和JDK 8中hash方…

python下面的代码_解析一下下面的python代码?

class Model(dict, metaclassModelMetaclass): # 初始化, 没啥好说的 def __init__(self, **kw): super(Model, self).__init__(**kw) # 如果取不到值, 报错, 这是一个魔术方法, 使用时直接getattr(obj, key) def __getattr__(self, key): try: return self[key] except KeyErr…

SpringBoot多数据源(主从数据源)配置

&#x1f3b6;前言 学习springboot配置多数据源&#xff0c;先回顾一下springboot配置单数据源的方式 SpringBoot配置mybatis-mysql数据源 &#x1f520;主从数据源搭建 项目依赖 本次记录多数据源配置主要是通过druid mybatis plus aop的形式实现的&#xff0c;mybatis …

(转)HttpURLConnection与 HttpClient 区别

转自&#xff1a; HttpURLConnection与 HttpClient 区别/性能测试对比 - 尚码园HttpURLConnection与HttpClient随笔   目前在工做中遇到的须要各类对接接口的工做&#xff0c;须要用到HTTP的知识&#xff0c;工做完成后想要作一些笔记&#xff0c;原本知识打算把本身写的代码…

Raspkate - 基于.NET的可运行于树莓派的轻量型Web服务器

最近在业余时间玩玩树莓派&#xff0c;刚开始的时候在树莓派里写一些基于wiringPi库的C语言程序来控制树莓派的GPIO引脚&#xff0c;从而控制LED发光二极管的闪烁&#xff0c;后来觉得&#xff0c;是不是可以使用HTML5jQuery等流行的前端技术做一个简单的Web站点&#xff0c;让…

深入分析Java中的length和length()

转载自 深入分析Java中的length和length()在开始正文之前&#xff0c;请你快速回答如下问题&#xff1a;在不使用任何带有自动补全功能IDE的情况下&#xff0c;如何获取一个数组的长度&#xff1f;以及&#xff0c;如何获取一个字符串的长度&#xff1f;这个问题我问过不同水平…