Java创建实例方法的区别 小咪咪 2021-11-16 13:46 272阅读 0赞 近来打算自己封装一个比较方便读写的Office Excel 工具类,前面已经写了一些,比较粗糙本就计划重构一下,刚好公司的电商APP后台原有的导出Excel实现出现了可怕的性能问题,600行的数据生成Excel工作簿居然需要50秒以上,客户端连接都被熔断了还没导出来,挺巧,那就一起解决吧。 对于消息中间件RabbitMQ,想必各位小伙伴没有用过、也该有听过,它是一款目前市面上应用相当广泛的消息中间件,可以实现消息异步通信、业务服务模块解耦、接口限流、消息分发等功能,在微服务、分布式系统架构中可以说是充当着一名了不起的角色!(详细的介绍,Debug在这里就不赘述了,各位小伙伴可以上官网看看其更多的介绍及其典型的应用场景)! 在本篇博文中,我们将使用RabbitMQ充当消息发送的组件,将它与后面篇章介绍的“邮件服务”结合实现“用户秒杀成功后异步发送邮件通知消息,告知用户秒杀已经成功!”,下面我们一起进入代码实战吧。 在上一个版本里呢,我认为比较巧妙的地方在于用函数式编程的方式代替反射,很早以前了解了反射的一些底层后我就知道反射的性能很差,但一直没实际测试过各种调用场景的性能差距。 至于底层字节码、CPU指令这些我就不深究了,我还没到那个级别,那这次就来个简单的测试吧。 目标:创建Man对象。 方式: ① 直接引用 new Man(); ② 使用反射 ③ 使用内部类 ④ 使用Lombda表达式 ⑤ 使用Method Reference 在学习Java8新特性的时候,我所了解到的是Lombda表达式是内部类的一种简化书写方式,也就是语法糖,但两者间在运行时居然有比较明显的性能差距,让我不得不怀疑它底层到底是啥东西,时间精力有限先记着,有必要的时候再去啃openJDK吧。 还有就是Lombda和Method Reference从表现来看,底层应该是同一个东西,但IDEA既然分开两种内部类的写法推荐,那就分开对待吧。 测试时每种方式循环调用 1 亿次,每种方式连续计算两次时间,然后对比第二次运行的结果,直接run没有采用debug运行。 贴代码: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NkMDkwNDQ5MDFndWlj_size_16_color_FFFFFF_t_70][] 紧接着,我们借助SpringBoot天然具有的一些特性,自动注入RabbitMQ一些组件的配置,包括其“单一实例消费者”配置、“多实例消费者”配置以及用于发送消息的操作组件实例“RabbitTemplate”的配置: //通用化 Rabbitmq 配置 @Configuration public class RabbitmqConfig { private final static Logger log = LoggerFactory.getLogger(RabbitmqConfig.class); @Autowired private Environment env; @Autowired private CachingConnectionFactory connectionFactory; @Autowired private SimpleRabbitListenerContainerFactoryConfigurer factoryConfigurer; //单一消费者 @Bean(name = "singleListenerContainer") public SimpleRabbitListenerContainerFactory listenerContainer(){ SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); factory.setConnectionFactory(connectionFactory); factory.setMessageConverter(new Jackson2JsonMessageConverter()); factory.setConcurrentConsumers(1); factory.setMaxConcurrentConsumers(1); factory.setPrefetchCount(1); factory.setTxSize(1); return factory; } //多个消费者 @Bean(name = "multiListenerContainer") public SimpleRabbitListenerContainerFactory multiListenerContainer(){ SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); factoryConfigurer.configure(factory,connectionFactory); factory.setMessageConverter(new Jackson2JsonMessageConverter()); //确认消费模式-NONE factory.setAcknowledgeMode(AcknowledgeMode.NONE); factory.setConcurrentConsumers(env.getProperty("spring.rabbitmq.listener.simple.concurrency",int.class)); factory.setMaxConcurrentConsumers(env.getProperty("spring.rabbitmq.listener.simple.max-concurrency",int.class)); factory.setPrefetchCount(env.getProperty("spring.rabbitmq.listener.simple.prefetch",int.class)); return factory; } @Bean public RabbitTemplate rabbitTemplate(){ connectionFactory.setPublisherConfirms(true); connectionFactory.setPublisherReturns(true); RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory); rabbitTemplate.setMandatory(true); rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() { @Override public void confirm(CorrelationData correlationData, boolean ack, String cause) { log.info("消息发送成功:correlationData({}),ack({}),cause({})",correlationData,ack,cause); } }); rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() { @Override public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) { log.warn("消息丢失:exchange({}),route({}),replyCode({}),replyText({}),message:{}",exchange,routingKey,replyCode,replyText,message); } }); return rabbitTemplate; } } 直接查看实现,会发现 `onSubscribe()` 中做了一些判断,比如 `82` `104` 等几行都是做了一些 `同步` `异步` 等的判断,然后初始化 `Disposable` , `onSubscribe()` 是上游 `Observable` 完成了整条订阅链之后调用的,所以这些操作是在开始订阅之后才初始化操作,然后 `106` 行可以看出把一个包装处理过的 `Disposable` 传递给下游。 查看一下这个scheduler的worker,会发现worker的基类schedule()方法是相同的互相调用的,所以可以直接看多个参数的schedule(),可以看到 `73` 行创建了一个 `ScheduledRunnable` 对象,并且把 `主线程的handler` 以及外面的 `Observer` 传递过去,接着 `82` 行用主线程的handler发送消息, `119` 行 `ScheduledRunnable` 里的 `run` 被调用,接着 `Observer也就是runnable` 也调用 `run`方法 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NkMDkwNDQ5MDFndWlj_size_16_color_FFFFFF_t_70]: /images/20211116/914e8a3c50e442c8adc35e401d988653.png
相关 详解Java中静态方法和实例方法的区别 在Java编程语言中,静态方法和实例方法是两种不同的方法定义方式。以下是它们的主要区别: 1. **调用方式**: - 实例方法:需要一个具体的对象(实例)来调用,例如 刺骨的言语ヽ痛彻心扉/ 2024年09月17日 11:21/ 0 赞/ 10 阅读
相关 混淆概念:Java中的静态方法和实例方法区别 在Java编程中,静态方法(Static Method)和实例方法(Instance Method)有以下几个显著的区别: 1. 调用方式: - 静态方法:不依赖于任何具体对 曾经终败给现在/ 2024年09月16日 06:03/ 0 赞/ 11 阅读
相关 Java中静态方法和实例方法的区别 在Java中,静态方法(Static Method)和实例方法(Instance Method)主要区别在于它们的作用域、创建方式以及与对象的关系。 1. 作用域: - 实例 柔情只为你懂/ 2024年09月15日 11:18/ 0 赞/ 21 阅读
相关 Java中静态方法和非静态方法的区别实例 在Java编程语言中,静态方法(Static Methods)和非静态方法(Non-Static Methods)有以下几个主要区别: 1. 调用方式: - 非静态方法 迈不过友情╰/ 2024年09月12日 02:39/ 0 赞/ 27 阅读
相关 java静态变量与实例变量、静态方法与实例方法的区别 静态变量与实例变量 > 语法上的区别:静态变量定义前要加关键字static,而实例变量不用 > > 实例变量:当创建一个类的对象时,该对象就会拥有一份属于自己的全部数据 古城微笑少年丶/ 2022年09月30日 10:51/ 0 赞/ 169 阅读
相关 使用工厂方法模式创建实例(JAVA版) 工厂方法模式简介 工厂方法模式中的接口工厂负责定义创建对象的方法,具体对象的创建由实现抽象工厂接口的实现类完成。 工厂方法的优点:不需要使用者(客户端)去创建. 桃扇骨/ 2022年07月11日 01:44/ 0 赞/ 128 阅读
相关 Java中类方法与实例方法的区别 Java中类的方法分为类方法(用static修饰,也叫静态方法)和实例方法(没有用static修饰,也叫非静态方法),这两种方法之间有什么区别呢? 一. 实例方法 当类的字 红太狼/ 2022年06月02日 09:22/ 0 赞/ 170 阅读
相关 java中静态方法和实例方法的区别 1.在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。 2.静态方 红太狼/ 2022年02月02日 00:13/ 0 赞/ 315 阅读
相关 Java创建实例方法的区别 近来打算自己封装一个比较方便读写的Office Excel 工具类,前面已经写了一些,比较粗糙本就计划重构一下,刚好公司的电商APP后台原有的导出Excel实现出现了可怕的性能 小咪咪/ 2021年11月16日 13:46/ 0 赞/ 273 阅读
还没有评论,来说两句吧...