<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[Zmj的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/JavaMrZhang</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; JavaMrZhang]]></copyright><item><title><![CDATA[P2P网络NAT穿透原理(打洞方案)]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/132005278</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/132005278</guid><author>JavaMrZhang</author><pubDate>Sun, 30 Jul 2023 11:51:36 +0800</pubDate><description><![CDATA[若通讯协议的内容中有IP地址的传递，如FTP协议，NAT在转换时还要把数据包内涉及协议地址交互的地方替换，否则协议就会出现地址混乱。NAT的内外网通讯双方不是平等的，允许内网机器主动发起连接访问外网，当NAT没有对应的地址转换映射表项时，会建立一个映射表项，数据包经过NAT地址转换后发送给外网的服务器，连接建立以后可双向传送数据，但却禁止反方向的主动访问：在没有对应地址映射表项情况下，不允许外网主动访问内网主机，因为没有对应的地址映射表项用于转换地址，外网发送的数据包会被丢弃。]]></description><category></category></item><item><title><![CDATA[一个基于Spring Boot+Vue+Redis的物联网智能家居系统]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/122086243</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/122086243</guid><author>JavaMrZhang</author><pubDate>Wed, 22 Dec 2021 15:08:45 +0800</pubDate><description><![CDATA[平台简介

若依是一套全部开源的快速开发平台，毫无保留给个人及企业免费使用。


	前端采用Vue、Element UI。
	
	
	后端采用Spring Boot、Spring Security、Redis &amp; Jwt。
	
	
	权限认证使用Jwt，支持多终端认证系统。
	
	
	支持加载动态权限菜单，多方式轻松权限控制。
	
	
	高效率开发，使用代码生成器可以一键生成前后端代码。
	
内置功能


	用户管理：用户是系统操作者，该功能主要完成系统用户配置。
	
	
	部门管理：配置系统组织机]]></description><category></category></item><item><title><![CDATA[Java9、10、11的新特性]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/117913582</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/117913582</guid><author>JavaMrZhang</author><pubDate>Mon, 14 Jun 2021 22:03:25 +0800</pubDate><description><![CDATA[Java 9
Java 9 提供了超过150项新功能特性，包括备受期待的模块化系统、可交互
的 REPL 工具,jshell，JDK 编译工具，Java 公共 API 和私有代码，以及安 全增强、扩展提升、性能管理改善等，下面介绍一些常用新特性。
1. JDK 目录结构的改变
JDK1.8及以前的目录

JDK1.9目录

2. 模块化系统
Java 已经 发展超过 20 年(95 年最初发布)，Java 和相关生态在不断丰富的同时也越来越暴露出一些问题:

Java 运行环境的膨胀和臃肿，每次JVM启动的]]></description><category></category></item><item><title><![CDATA[这也太简单了！！Zookeeper核心ZAB协议]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/115297083</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/115297083</guid><author>JavaMrZhang</author><pubDate>Mon, 29 Mar 2021 11:24:06 +0800</pubDate><description><![CDATA[ZAB协议是什么？
ZAB 协议全称：Zookeeper Atomic Broadcast（Zookeeper 原子广播协议）， 它保证Zookeeper 在主从系统架构下，集群中各个节点之间数据的一致性。保证数据一致性的分两种情况讨论，一种集群正常运行，一种集群不正常。
Zookeeper集群正常运行时采用消息广播模式保证；
Leader节点宕机情况下采用崩溃恢复模式，保证；
消息广播
消息广播，就是集群正常运行时接收客户端写请求，需要保证集群数据的一致。
消息广播是一个原子广播协议，类似二阶段提交过程。]]></description><category></category></item><item><title><![CDATA[Zookeeper 的选举机制也不过如此！]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/115226184</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/115226184</guid><author>JavaMrZhang</author><pubDate>Fri, 26 Mar 2021 09:12:48 +0800</pubDate><description><![CDATA[Zookeeper 是一个分布式服务框架，主要是用来解决分布式应用中遇到的一些数据管理问题如：统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。
我们可以简单把 Zookeeper 理解为分布式家庭的大管家，那么管家团队是如何选出Leader的呢？好奇吗，接下来带领大家一探究竟。
人类选举的基本原理
讲解 Zookeeper 选举过程前先来介绍一下人类的选举。
我们每个人或多或少都经历过几次选举，在投票的过程中可能会遇到这样几种情况：
情况1：自己和候选人熟，将票投给你认为能力强的那个人；
情]]></description><category></category></item><item><title><![CDATA[处理 Exception 的几种实践，很优雅，被很多团队采纳！]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/115199136</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/115199136</guid><author>JavaMrZhang</author><pubDate>Thu, 25 Mar 2021 10:17:46 +0800</pubDate><description><![CDATA[在Java中处理异常并不是一个简单的事情。不仅仅初学者很难理解，即使一些有经验的开发者也需要花费很多时间来思考如何处理异常，包括需要处理哪些异常，怎样处理等等。
这也是绝大多数开发团队都会制定一些规则来规范对异常处理的原因。而团队之间的这些规范往往是截然不同的。
本文给出几个被很多团队使用的异常处理最佳实践。
实践
在Finally块中清理资源或者使用try-with-resource语句
当使用类似InputStream这种需要使用后关闭的资源时，一个常见的错误就是在try块的最后关闭资源。
public]]></description><category></category></item><item><title><![CDATA[面试再问你CAP、BASE 理论是什么？这篇文章仍甩给他！]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/113259060</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/113259060</guid><author>JavaMrZhang</author><pubDate>Wed, 27 Jan 2021 17:51:01 +0800</pubDate><description><![CDATA[作者：架构师小白, 来源：公众号-程序员虎哥

前言
什么是分布式事务？介绍这个之前，先了解下这几个问题

事务是什么？
本地事务是什么？
分布式是什么？
分布式事务是什么？

事务是什么？
完成某件事情，可能有多个参与者需要执行多个步骤，最终多个步骤要么全部成功，要么全部失败。
举个栗子：支付宝上A给B转账100元，A账户扣100，B账户增加100，这就是一个事务，这个操作中要么都成功，要么都失败。
事务的场景有很多，参与者也是多种多样。比如


用户成功注册然后发送邮件，包含2个操作：向数据库插入用户.]]></description><category></category></item><item><title><![CDATA[特好用！！！8种分布式ID生成方法]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/113172682</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/113172682</guid><author>JavaMrZhang</author><pubDate>Tue, 26 Jan 2021 09:02:07 +0800</pubDate><description><![CDATA[前言
业务量小于500W或数据容量小于2G的时候单独一个mysql即可提供服务，再大点的时候就进行读写分离也可以应付过来。但当主从同步也扛不住的时候就需要分表分库了，但分库分表后需要有一个唯一ID来标识一条数据，且这个唯一ID还必须有规则，能辅助我们解决分库分表的一些问题。
数据库的自增ID显然不能满足需求；特别一点的如订单、优惠券也都需要有唯一ID做标识。此时一个能够生成全局唯一ID的系统是非常必要的，那么这个全局唯一ID就叫分布式ID。
分布式ID需满足那些条件

全局唯一：基本要求就是必须保证ID是全]]></description><category></category></item><item><title><![CDATA[面试Java后端开发总结心得，很走心的文章（附面试题）]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/113034051</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/113034051</guid><author>JavaMrZhang</author><pubDate>Sat, 23 Jan 2021 11:24:49 +0800</pubDate><description><![CDATA[在上周，我密集面试了若干位Java后端的候选人，工作经验在3到5年间。我的标准其实不复杂：第一能干活，第二Java基础要好，第三最好熟悉些分布式框架。我相信其它公司招初级开发时，应该也照着这个标准来面的。

我也知道，不少候选人能力其实不差，但面试时没准备或不会说，这样的人可能在进团队干活后确实能达到期望，但可能就无法通过面试，但面试官总是只根据面试情况来判断。

但现实情况是，大多数人可能面试前没准备，或准备方法不得当。要知道，我们平时干活更偏重于业务，不可能大量接触到算法，数据结构，底层代码这类面试必问]]></description><category></category></item><item><title><![CDATA[女朋友也能看懂的Zookeeper分布式锁原理]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/112986422</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/112986422</guid><author>JavaMrZhang</author><pubDate>Fri, 22 Jan 2021 15:34:28 +0800</pubDate><description><![CDATA[介绍
许多场景中，数据一致性是一个比较重要的话题，在单机环境中，我们可以通过Java提供的并发API来解决；而在分布式环境(会遇到网络故障、消息重复、消息丢失等各种问题)下要复杂得多，比如电商的库存扣减，秒杀活动，集群定时任务执行等需要进程互斥的场景。本文主要探讨如何利用Zookeeper来实现分布式锁，对比了一些其他方案分布式锁的优缺点。至于使用何种，要因自己的业务场景去决定，没有绝对的方案。
分布式锁是什么？
分布式锁是控制分布式系统之间同步访问共享资源的一种方式。
实现分布式锁注意点：

锁的可重入性]]></description><category></category></item><item><title><![CDATA[灵魂发问！线程池到底创建多少线程比较合理？]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/112967908</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/112967908</guid><author>JavaMrZhang</author><pubDate>Thu, 21 Jan 2021 17:30:13 +0800</pubDate><description><![CDATA[虽然线程池的模型被剖析的非常清晰，但是如何最高性能地使用线程池一直是一个令人纠结的问题，其中最主要的问题就是如何决定线程池的大小。这篇文章会以量化测试的方式分析：何种情况线程池应该使用多少线程数。
计算密集型任务与IO密集型任务
大多数刚接触线程池的人会认为有一个准确的值作为线程数能让线程池适用在程序的各个地方。然而大多数情况下并没有放之四海而皆准的值，很多时候我们要根据任务类型来决定线程池大小以达到最佳性能。
计算密集型任务以CPU计算为主，这个过程中会涉及到一些内存数据的存取（速度明显快于IO），执行任]]></description><category></category></item><item><title><![CDATA[为什么牛逼的程序员都不用 “ ! = null “ 做判空？]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/112868378</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/112868378</guid><author>JavaMrZhang</author><pubDate>Wed, 20 Jan 2021 14:29:55 +0800</pubDate><description><![CDATA[问题

为了避免空指针调用，我们经常会看到这样的语句


...
if(someobject!=null){
someobject.doCalc();
}
...


最终，项目中会存在大量判空代码，多么丑陋繁冗！如何避免这种情况？我们是否滥用了判空呢？

精华回答

这是初、中级程序猿经常会遇到的问题。他们总喜欢在方法中返回null，因此，在调用这些方法时，也不得不去判空。另外，也许受此习惯影响，他们总潜意识地认为，所有的返回都是不可信任的，为了保护自己程序，就加了大量的判空。

...]]></description><category></category></item><item><title><![CDATA[浅谈Mybatis的一级缓存和二级缓存]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/110071072</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/110071072</guid><author>JavaMrZhang</author><pubDate>Tue, 24 Nov 2020 14:06:49 +0800</pubDate><description><![CDATA[MyBatis的缓存机制

缓存的引入

当我们大量执行重复的查询SQL语句的时候,会频繁的和数据库进行通信,会增加查询时间等影响用户体验的问题,可以通过缓存，以降低网络流量，使网站加载速度更快.

MyBatis的一级缓存

默认情况下，MyBatis只启用了本地的会话缓存，它仅仅对一个会话中的数据进行缓存。这也就是大家常说的MyBatis一级缓存，一级缓存的作用域是SqlSession。

第1种情况：同个session进行两次相同查询

代码验证


    //测试一级缓存
    @Test
  ]]></description><category></category></item><item><title><![CDATA[[转]Java校招入职华为，半年后我跑路了]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/105053666</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/105053666</guid><author>JavaMrZhang</author><pubDate>Mon, 23 Mar 2020 17:44:43 +0800</pubDate><description><![CDATA[0 前言

全是干货的技术殿堂


文章收录在我的 GitHub 仓库，欢迎Star/fork：Java-Interview-Tutorial
https://github.com/Wasabi1234/Java-Interview-Tutorial


1 何来?

我，一个双非本科弟弟，有幸在 19 届的秋招中得到前东家华为（以下简称 hw）的赏识，当时秋招签订就业协议，当时 18 年1...]]></description><category></category></item><item><title><![CDATA[ThreadPoolExecutor最佳实践--如何选择线程数]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/104050946</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/104050946</guid><author>JavaMrZhang</author><pubDate>Mon, 20 Jan 2020 13:58:25 +0800</pubDate><description><![CDATA[去年的一篇《ThreadPoolExecutor详解》大致讲了ThreadPoolExecutor内部的代码实现。

总结一下，主要有以下四点：

当有任务提交的时候，会创建核心线程去执行任务（即使有核心线程空闲仍会创建）；
	当核心线程数达到corePoolSize时，后续提交的都会进BlockingQueue中排队；
	当BlockingQueue满了(offer失败)，就会创建临时线程(临时...]]></description><category></category></item><item><title><![CDATA[Maven依赖详解]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/91356176</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/91356176</guid><author>JavaMrZhang</author><pubDate>Sun, 09 Jun 2019 19:40:04 +0800</pubDate><description><![CDATA[本篇目标：通过讲解maven依赖范围、传递性依赖、可选依赖、依赖调节，让大家知道maven依赖的正确使用姿势是什么。

什么是依赖范围
Java在进行代码编译和运行的时候都分别需要指定classpath路径，不然将会出现找不到对应的类。同样的maven默认提供了编译主代码时、测试代码时、运行时的3套classpath。而依赖范围就是用来控制该jar应该被引入哪一个classpath中，maven...]]></description><category></category></item><item><title><![CDATA[ThreadPoolExecutor入门级]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/89881285</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/89881285</guid><author>JavaMrZhang</author><pubDate>Mon, 06 May 2019 13:59:33 +0800</pubDate><description><![CDATA[是什么
JUC包下提供的一个线程池工具类。它帮我们解决了2个主要问题：

当需要执行大量异步任务的时候合理、有效的复用线程资源，防止多个任务创建多个线程资源。
能够有效限制和管理线程资源，比如控制初始化线程的数量，动态新增线程数等。

实现原理
本篇我们主要围绕它的核心设计思想讲解，不追踪源码。JUC包下提供了Excutors工厂类，让我们快速便捷的实例化ThreadPoolExecutor，但更...]]></description><category></category></item><item><title><![CDATA[Redis入门篇（2）- 奇淫技巧]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/89881255</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/89881255</guid><author>JavaMrZhang</author><pubDate>Mon, 06 May 2019 13:57:56 +0800</pubDate><description><![CDATA[慢查询
许多的存储系统都提供了慢查询的配置，来帮助开发和运维排查线上哪些指令执行的时间耗时过长导致系统响应过慢。同样的Redis也不逊色，也提供了类似慢查询指令的配置。
Redis主要提供了两个配置属性slowlog-log-slower-than和slowlog-max-len，来配置慢查询指令的记录规则。

slowlog-log-slower-than

设置指令执行时间的阀值，如果超过该时...]]></description><category></category></item><item><title><![CDATA[Redis入门篇（1）-类型技能]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/89881221</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/89881221</guid><author>JavaMrZhang</author><pubDate>Mon, 06 May 2019 13:56:32 +0800</pubDate><description><![CDATA[字符串
首先Redis数据存储都会以key value 的形式进行存放， 所有的key都是字符串类型。此处所说的类型特指的是value中存放的类型。下文所讲的hash、列表都是基于value上进行讲解的。Redis会根据传入字符串类型规则进行判断，并采取相应的内部编码进行存储。数值型会采用8个字节的长整型进行编码存储，小于等于39个字节的字符串采用emstr编码存储，大于39字节的字符串采用raw...]]></description><category></category></item><item><title><![CDATA[ReentrantReadWriteLock入门级]]></title><link>https://blog.youkuaiyun.com/JavaMrZhang/article/details/89454091</link><guid>https://blog.youkuaiyun.com/JavaMrZhang/article/details/89454091</guid><author>JavaMrZhang</author><pubDate>Mon, 22 Apr 2019 16:09:18 +0800</pubDate><description><![CDATA[是什么
解决线程安全我们用ReentrantLock就可以了，但是对于读多写少的情况下我们继续使用它会有损性能，因为在没有写但有持续读数据的情况下，加锁是没有必要的，所以ReentrantReadWriteLock为了解决这个问题应运而生，它满足这样的规则：读读共享、读写互斥、写写互斥。更进一步的解释，它内部维护了两种锁即写锁和读锁。在没有线程获取写锁的时候，多个线程可以同时获取读锁。如果有线程获...]]></description><category></category></item></channel></rss>