
版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 https://blog.csdn.net/chszs/article/details/81509169 Java编程中资源对象管理的进化 2018.8.8 版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 使用Java开发业务时,常常需要处理资源,这是很常见的需求。 Java 7以前 在Java 7以前,处理(关闭)资源是这样的: public static int getAccountStatusCodeFromDataStore_traditional(String accountId) throws SQLException { String accountStatusCodeQuery = getAccountStatusCodeQuery(accountId); Statement statement = null; ResultSet resultSet = null; try { statement = createStatementFromConnection(); resultSet = statement.executeQuery(accountStatusCodeQuery); return getAccountStatusCodeFromResultSet(resultSet); } finally { if (resultSet != null) resultSet.close(); if (statement != null) statement.close(); } } 开发人员必须关闭创建的所有资源,否则会导致资源泄漏。 Java 7/8 而在Java 7中,引入了try-with-resources的新方法,可以在try-catch块中使用的正确顺序自动处理资源的关闭,比如: public static int getAccountStatusCodeFromDataStore_java7(String accountId) throws SQLException { String accountStatusCodeQuery = getAccountStatusCodeQuery(accountId); try (Statement statement = createStatementFromConnection(); ResultSet resultSet = statement.executeQuery(accountStatusCodeQuery)) { return getAccountStatusCodeFromResultSet(resultSet); } } 在此示例中,可以看到代码更简洁了,整体可读性提高了,它实现了资源的自动管理。我们可以在try-with-resources语句中拥有多个资源,且多个资源的声明之间应该用分号分隔。当这些资源在自动关闭时,也会保持声明的反向逻辑顺序依次关闭(最后声明的资源将首先关闭)。 如果这里要抛出异常,try块的异常会会压制try-with-resources块的异常。如果确实有需要,可以通过从try块抛出的异常中调用Throwable.getSuppressed方法来检索被try块抑制的异常。 另外,try-with-resources语句也可以有catch和finally块。在声明的资源被关闭后会运行任何catch或finally块。 Java 9 而到了Java 9时代,对于try-with-resources的资源处理,Java 9中引入了更简洁的版本。如果开发者已经将资源声明为final或effective final类型,那么可以在try-with-resources中直接使用它们而无需创建任何新变量。这使得我们可以进一步利用自动资源管理。上面的代码现在可使用更简洁的try-with-resources实现,如下: public static int getAccountStatusCodeFromDataStore_java9(String accountId) throws SQLException { String accountStatusCodeQuery = getAccountStatusCodeQuery(accountId); // 明确声明final final Statement statement = createStatementFromConnection(); // effective final ResultSet resultSet = statement.executeQuery(accountStatusCodeQuery); try (statement; resultSet) { return getAccountStatusCodeFromResultSet(resultSet); } } 可见,代码的易读性提高了。 其实大多数的资源类在背后实现了AutoCloseable或Closeable接口,因此与try-with-resources语句协同工作才实现了自动资源管理。如果我们处理的资源没有实现AutoCloseable或Closeable接口,那么就必须遵循传统的方法来关闭资源。
版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 https://blog.csdn.net/chszs/article/details/81042018 实现Java集合迭代的高性能 2018.7.14 版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 一、介绍 Java开发者经常会遇到处理集合(比如ArrayList、HashSet)的情况,Java 8也提供了Lambda表达式和Streaming API来简化集合相关的工作。在大多数应用场景下,无需考虑集合迭代的性能消耗。但是,在一些极端情况下,比如集合包含了上百万条记录的情况,这个时候集合迭代就需要选择正确的姿势,否则性能会较差。 使用JMH检查下面每段代码片段的运行时间。 二、forEach vs. C Style vs. Stream API 迭代是一个非常基本的功能,所有的编程语言都有简单的迭代语法,允许程序员在集合上运行迭代。Stream API可以通过Collections用非常直接的方式进行迭代。 public List<Integer> streamSingleThread(BenchMarkState state) { List<Integer> result = new ArrayList<>(state.testData.size()); state.testData.stream().forEach(item -> { result.add(item); }); return result; } public List<Integer> streamMultiThread(BenchMarkState state) { List<Integer> result = new ArrayList<>(state.testData.size()); state.testData.stream().parallel().forEach(item -> { result.add(item); }); return result; } 使用forEach循环也非常简单: public List<Integer> forEach(BenchMarkState state) { List<Integer> result = new ArrayList<>(state.testData.size()); for(Integer item : state.testData) { result.add(item); } return result; } C style方式的迭代其代码要冗长一些,但仍然非常紧凑: public List<Integer> forCStyle(BenchMarkState state) { int size = state.testData.size(); List<Integer> result = new ArrayList<>(size); for(int j = 0; j < size; j ++){ result.add(state.testData.get(j)); } return result; } 以上代码的性能评分如下: Benchmark Mode Cnt Score Error Units TestLoopPerformance.forCStyle avgt 200 18.068 ± 0.074 ms/op TestLoopPerformance.forEach avgt 200 30.566 ± 0.165 ms/op TestLoopPerformance.streamMultiThread avgt 200 79.433 ± 0.747 ms/op TestLoopPerformance.streamSingleThread avgt 200 37.779 ± 0.485 ms/op 对于C style方式的迭代,JVM只是简单地增加了一个整型变量,它直接从内存读值。这使它非常快。但forEach迭代则不同,根据Oracle官方文档,JVM必须把forEach转换为迭代器并为每个数据项调用hasNext()。这就是为什么forEach比C style
版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 https://blog.csdn.net/chszs/article/details/80502641 MariaDB TX 3.0企业开源数据库 2018.5.29 版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 MariaDB TX是一款开源的、基于MariaDB的企业数据库解决方案,它具有轻量级连接器、高级数据库代理和防火墙、可插拔的通用数据库、专用存储引擎、多主集群,并为数据库管理员和开发人员提供了通知服务。 MariaDB TX刚发布了最新的3.0版本。 MariaDB TX 3.0新特性 1. 引入了对Oracle数据库的兼容性 支持包含Oracle数据类型、控制语句,静态和动态SQL(包括带参数的游标)、触发器、序列和存储过程/函数。 MariaDB TX 3.0是第一个具有Oracle数据库兼容性的企业开源数据库,包括对使用PL/SQL编写的存储过程的支持。到目前为止,如果需要Oracle数据库兼容性,就需要专用数据库(如IBM DB2或EnterpriseDB),现在又多了一个选择。 2. 临时表和查询 引入了内建的系统版本化表(SVT,System-Versioned Table)来自动、透明地存储数据行的当前和历史版本,以及基于特定时间点,在两个特定时间点或所有时间之间查询它们的SQL语法。 到目前为止,如果需要Oracle闪回(Flashback)查询功能或Microsoft SQL Server临时表功能,都需要专有数据库。而现在可以选择MariaDB TX。 3. 专用存储 MariaDB TX 3.0引入了MyRocks引擎的一般可用性,MyRocks是Facebook开发的针对空间优化和写入优化的存储引擎,推荐用于写密集型工作负载的场景;还引入了Spider引擎,Spider引擎是官方推荐的适合存储、写入的可伸缩性和并发性的分布式存储引擎。 MariaDB TX 3.0是第一款支持多种工作负载的企业开源数据库,它们都具有相同级别的性能,它利用了多种专用存储引擎: 用于混合或读取为主要工作负载的场景:InnoDB引擎,也是默认的存储引擎 用于写入密集型工作负载、针对SSD优化的场景:MyRocks引擎 用于需要极高可伸缩性和并发性的场景:Spider引擎 4. 高级安全性 MariaDB TX 3.0引入了部分数据屏蔽和全面数据模糊处理,以保护敏感安全和个人身份信息免受未经授权的访问,这是遵循法规所必需的,包括欧盟通用数据保护条例GDPR。 MariaDB TX 3.0的企业可靠性 高可用性:通过集群、复制和自动故障转移功能确保关键任务应用的正常运行时间。 性能:通过多核处理器和多线程架构满足用户对性能的期望。 灾难恢复:通过备份和恢复或时间点回滚功能搞定非预期的故障恢复。 可扩展性:通过分布式、多主存储功能实现按需扩展来适应业务的持续增长。 安全:使用角色、加密、数据保护、数据混淆/屏蔽和查询阻止来保护客户的数据。 架构的灵活性:使用内建的JSON函数创建混合数据模型并能即时添加列。 MariaDB TX 3.0的高可用性 自动故障转移 透明的查询路由 多主集群 无损半同步复制 多源复制
版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 https://blog.csdn.net/chszs/article/details/80354356 Protostuff使用示例 2018.5.17 版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 1、引入Maven依赖的JAR包 <dependency> <groupId>io.protostuff</groupId> <artifactId>protostuff-core</artifactId> <version>1.5.9</version> </dependency> <dependency> <groupId>io.protostuff</groupId> <artifactId>protostuff-runtime</artifactId> <version>1.5.9</version> </dependency> <dependency> <groupId>io.protostuff</groupId> <artifactId>protostuff-api</artifactId> <version>1.5.9</version> </dependency> 2、编写需要被序列化的实体类 这里是User.java(成员属性包含了其它类) package demo.protostuff; import java.util.List; public class User { private String firstName; private String lastName; private String email; private List<User> friends; private List<Car> cars; public User() { } public User(String email) { this.email = email; } // getters and setters public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public List<User> getFriends() { return friends; } public void setFriends(List<User> friends) { this.friends = friends; } public List<Car> getCars() { return cars; } public void setCars(List<Car> cars) { this.cars = cars; } @Override public String toString() { return "User{" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", email='" + email + '\'' + ", friends=" + friends + ", cars=" + cars + '}'; } } Car.java package demo.protostuff; public class Car { private String color; private String car_name; private Integer price; public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String getCar_name() { return car_name; } public void setCar_name(String car_name) { this.car_name = car_name; } public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } public Car(String car_name) { super(); this.car_name = car_name; } public Car() { super(); } @Override public String toString() { return "Car [color=" + color + ", car_name=" + car_name + ", price=" + price + "]"; } } 3、主程序类 这里是App.java package demo.protostuff; import java.util.ArrayList; import java.util.List; import io.protostuff.LinkedBuffer; import io.protostuff.ProtostuffIOUtil; import io.protostuff.runtime.RuntimeSchema; public class App { private static RuntimeSchema<User> schema = RuntimeSchema.createFrom(User.class); public static void main(String[] args) { User user1 = new User(); user1.setEmail("10000@qq.com"); user1.setFirstName("zhang"); user1.setLastName("sanfeng"); List<User> users = new ArrayList<>(); users.add(new User("20000@qq.com")); user1.setFriends(users); Car car1 = new Car("宾利"); Car car2 = new Car("法拉利"); List<Car> cars = new ArrayList<>(); cars.add(car1); cars.add(car2); user1.setCars(cars); byte[] bytes = ProtostuffIOUtil.toByteArray(user1, schema, LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE)); User user2 = schema.newMessage(); ProtostuffIOUtil.mergeFrom(bytes, user2, schema); System.out.println(user2); System.out.println(); // 使用自定义的工具类 byte[] bytes1 = ProtostuffUtil.serializer(user1); User newUser = ProtostuffUtil.deserializer(bytes1, User.class); System.out.println(newUser); } } 程序说明: RuntimeSchema类用于在运行时从Java实体对象中生成所需的模式Schema ProtostuffIOUtil是一个工具类,用于对消息或对象进行序列化/反序列化 LinkedBuffer是一个缓冲区类,它封装了字节数组并具有对下一个缓冲区的引用以便能动态增加容量。 执行程序,输出如下: User{firstName=’zhang’, lastName=’sanfeng’, email=’10000@qq.com’, friends=[User{firstName=’null’, lastName=’null’, email=’20000@qq .com’, friends=null, cars=null}], cars=[Car [color=null, car_name=宾利, price=null], Car [color=null, car_name=法拉利, price=null]]} User{firstName=’zhang’, lastName=’sanfeng’, email=’10000@qq.com’, friends=[User{firstName=’null’, lastName=’null’, email=’20000@qq .com’, friends=null, cars=null}], cars=[Car [color=null, car_name=宾利, price=null], Car [color=null, car_name=法拉利, price=null]]} 4、根据Protostuff库自行封装的工具类 这里是ProtostuffUtil.java package demo.protostuff; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import io.protostuff.LinkedBuffer; import io.protostuff.ProtostuffIOUtil; import io.protostuff.Schema; import io.protostuff.runtime.RuntimeSchema; public class ProtostuffUtil { private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<Class<?>, Schema<?>>(); private static <T> Schema<T> getSchema(Class<T> clazz) { @SuppressWarnings("unchecked") Schema<T> schema = (Schema<T>) cachedSchema.get(clazz); if (schema == null) { schema = RuntimeSchema.getSchema(clazz); if (schema != null) { cachedSchema.put(clazz, schema); } } return schema; } /** * 将对象序列化 * @param obj 对象 * @return */ public static <T> byte[] serializer(T obj) { @SuppressWarnings("unchecked") Class<T> clazz = (Class<T>) obj.getClass(); LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE); try { Schema<T> schema = getSchema(clazz); return ProtostuffIOUtil.toByteArray(obj, schema, buffer); } catch (Exception e) { throw new IllegalStateException(e.getMessage(), e); } finally { buffer.clear(); } } /** * 将字节数组数据反序列化 * @param data 字节数组 * @param clazz 对象 * @return */ public static <T> T deserializer(byte[] data, Class<T> clazz) { try { T obj = clazz.newInstance(); Schema<T> schema = getSchema(clazz); ProtostuffIOUtil.mergeFrom(data, obj, schema); return obj; } catch (Exception e) { throw new IllegalStateException(e.getMessage(), e); } } }
版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 https://blog.csdn.net/chszs/article/details/79980756 Nginx Unit详解系列(一) 2018.4.17 版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 一、什么是Nginx Unit Nginx Unit是一个开源的、以Nginx为基础的、支持多语言的动态Web应用服务器,它支持Python、PHP、Perl、Ruby和Go等多语言应用程序,可以在不中断服务的情况下完成部署配置更改,以多种语言运行代码。 Nginx Unit是一个新的开源项目,由Igor Sysoev发起,他说:“我想着手开发一款应用服务器,它能够远程动态配置,并且能够从一种语言的应用程序版本动态切换到另一种语言的应用程序。”Igor认为动态配置和交换无疑是主要问题,人们希望在不中断客户端处理的情况下重新配置服务器。 Nginx Unit使用REST API进行动态配置,它没有静态配置文件。所有配置更改直接在内存中发生,配置更改无需重新加载或服务中断即可生效。 Nginx Unit刚刚发布了1.0版,它可以在同一台服务器上支持Go、Perl、PHP、Python和Ruby,而且还支持多语言版本,比如用户可以在同一台服务器上同时运行PHP 5和PHP 7编写的应用程序。未来的Nginx Unit版本计划支持包括Java在内的其他语言。 NGINX Unit可以根据需要启动和扩展应用程序的进程,并在自己的安全沙箱中执行每一个应用程序实例。 Nginx Unit通过一个单独的“路由器”进程管理和路由所有传入网络通信到应用程序,因此它可以在不中断服务的情况下快速实施配置的更改。 Nginx Unit的配置采用了JSON格式,因此用户可以手动编辑,而且非常适合脚本编写。 Nginx Unit运行多种语言运行时的能力是基于它内部的路由器进程之间的隔离,路由器进程可终止传入的HTTP请求,以及应用程序进程的分组,它实现了应用程序运行时并执行应用程序代码。 路由器进程是持久的,它从不重新启动,意味着配置更新可以无缝地实现,而不会中断服务。每一个应用程序进程都部署在自己的沙箱中(在开发中支持Linux控制组 [cgroups]),以便Nginx Unit为用户代码提供安全的隔离。 二、Nginx Unit的下一步 Nginx Unit工程团队在发布1.0之后的下一个里程碑的内容主要是HTTP成熟度、静态内容服务和其他语言的支持。 “我们计划在单元中添加SSL和HTTP/2功能,”Igor说,“另外,我们计划在配置中支持路由。目前,我们有一个监听端口直接映射到一个应用程序,我们计划使用URI和主机名等添加路由。另外,我们希望为Unit增加更多的语言支持,我们正在完成Ruby实现,接下来我们将考虑Node.js和Java,Java将以Tomcat兼容的方式添加。” Nginx Unit的最终目标是为分布式多语言应用程序创建一个开源平台,该应用程序可以安全、可靠地运行应用程序代码并以最佳的性能运行。该平台将自行管理,具有自动调节功能以满足资源约束条件下的SLA,以及服务发现和内部负载平衡,以便轻松创建服务网格。 三、Nginx Unit和Nginx应用平台 Nginx Unit平台通常会提供Nginx开源的前端层或Nginx Plus反向代理,以提供入口控制,边缘负载均衡和安全性。然后可以使用Nginx控制器对联合平台(Nginx Unit和Nginx或Nginx Plus)进行全面管理,以监控、配置和控制整个平台。 这三个组件:Nginx Plus,Nginx Unit和Nginx Controller组成了Nginx应用平台。Nginx应用平台是一个产品套件,提供负载均衡、缓存、API管理、WAF和应用服务,并具有丰富的管理和控制面板,可简化单片应用、微服务和过渡应用的操作任务。