﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-JAVA-文章分类-java/J2EE</title><link>http://www.blogjava.net/zzzlyr/category/55171.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 24 Mar 2021 23:01:46 GMT</lastBuildDate><pubDate>Wed, 24 Mar 2021 23:01:46 GMT</pubDate><ttl>60</ttl><item><title>分布式锁实现-redis,zk </title><link>http://www.blogjava.net/zzzlyr/articles/435834.html</link><dc:creator>张钊钊</dc:creator><author>张钊钊</author><pubDate>Wed, 24 Mar 2021 12:11:00 GMT</pubDate><guid>http://www.blogjava.net/zzzlyr/articles/435834.html</guid><wfw:comment>http://www.blogjava.net/zzzlyr/comments/435834.html</wfw:comment><comments>http://www.blogjava.net/zzzlyr/articles/435834.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zzzlyr/comments/commentRss/435834.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zzzlyr/services/trackbacks/435834.html</trackback:ping><description><![CDATA[<div> 1:分布锁有好多实现方式</div><div><ul><li>&nbsp;基于数据库实现</li></ul><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个实现方式比较复杂,考虑因素比较多，比如：超时,非公平锁,非重入等会有各种各样的问题，在解决问题的过程中会使整个方案变得越来越复杂。操作数据库需要一定的开销，性能问题需要考虑&nbsp; &nbsp; &nbsp;&nbsp; </div><ul><li>基于redis实现(这个对于不太敏感的场景可以使用，由于redis集群和单机，还有客户端，版本等多方面因素考虑情况比较多)</li></ul><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 性能好。使用缓存实现分布式锁的缺点 其数据库一样</div><ul><li>基于zookeeper实现(这个是最终也是最好最可靠的)<br /></li></ul><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 创建临时节点，可以解决单机，锁无法释放，非阻塞，不可冲入，非公平的问题<br />&nbsp;</div><div>&nbsp;&nbsp;&nbsp; 总结<br /><blockquote>从理解的难易程度角度（从低到高）<br /><br />数据库 &gt; 缓存 &gt; Zookeeper<br /><br />从实现的复杂性角度（从低到高）<br /><br />Zookeeper &gt; 缓存 &gt; 数据库<br /><br />从性能角度（从高到低）<br /><br />缓存 &gt; Zookeeper &gt;= 数据库<br /><br />从可靠性角度（从高到低）<br /><br />Zookeeper &gt; 缓存 &gt; 数据库 <br /></blockquote>下面讲基于redis实现分布锁代码：RedisTemplate 客户端 <span style="color:#000080;font-weight:bold;">lettuce</span></div><div><span style="color:#000080;font-weight:bold;"><br /></span></div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; "><br /></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">@Service<br /></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;RedisDistributedLockUtils&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;@Autowired<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;RedisTemplate&nbsp;redisTemplate;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">final</span><span style="color: #000000; ">&nbsp;Long&nbsp;RELEASE_SUCCESS&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1L</span><span style="color: #000000; ">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">final</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">long</span><span style="color: #000000; ">&nbsp;DEFAULT_TIMEOUT&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1000</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">10</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">因为要使用lua&nbsp;脚本是因为&nbsp;redis&nbsp;执行lua脚本是原子操作</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">final</span><span style="color: #000000; ">&nbsp;String&nbsp;UNLOCK_LUA</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">if&nbsp;redis.call('get',&nbsp;KEYS[1])&nbsp;==&nbsp;ARGV[1]&nbsp;then&nbsp;return&nbsp;redis.call('del',&nbsp;KEYS[1])&nbsp;else&nbsp;return&nbsp;0&nbsp;end</span><span style="color: #000000; ">"</span><span style="color: #000000; ">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">/**</span><span style="color: #008000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;实时获取锁<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;尝试获取分布式锁&nbsp;将redis版本升级到2.1以上(spring-boot-starter-data-redis&nbsp;版本&nbsp;2.X以上)，然后使用setIfAbsent&nbsp;不存在<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;当setIfAbsent成功之后断开连接，下面设置过期时间的代码&nbsp;stringRedisTemplate.expire(key,timeout);是无法执行的，这时候就会有大量没有过期时间的数据存在数据库<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;lockKey&nbsp;&nbsp;&nbsp;&nbsp;锁<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;requestId&nbsp;&nbsp;请求标识<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;expireTime&nbsp;超期时间<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@return</span><span style="color: #008000; ">&nbsp;是否获取成功<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">boolean</span><span style="color: #000000; ">&nbsp;trySetDistributedLock(String&nbsp;lockKey,&nbsp;String&nbsp;requestId,&nbsp;</span><span style="color: #0000FF; ">long</span><span style="color: #000000; ">&nbsp;expireTime)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;redisTemplate.opsForValue().setIfAbsent(lockKey,&nbsp;requestId,</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;expireTime&nbsp;</span><span style="color: #000000; ">?</span><span style="color: #000000; ">&nbsp;DEFAULT_TIMEOUT&nbsp;:&nbsp;expireTime,&nbsp;TimeUnit.MILLISECONDS);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">/**</span><span style="color: #008000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;以阻塞方式的获取锁<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;key<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;value<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;timeout<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@return</span><span style="color: #008000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">boolean</span><span style="color: #000000; ">&nbsp;setDistributedLock(String&nbsp;key,&nbsp;String&nbsp;value,&nbsp;</span><span style="color: #0000FF; ">long</span><span style="color: #000000; ">&nbsp;timeout)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Boolean&nbsp;lock&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">long</span><span style="color: #000000; ">&nbsp;start&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;System.currentTimeMillis();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #000000; ">!</span><span style="color: #000000; ">lock&nbsp;</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; ">&nbsp;(System.currentTimeMillis()&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;start&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;timeout))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">执行set命令</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;redisTemplate.opsForValue().setIfAbsent(key,&nbsp;value,&nbsp;timeout,&nbsp;TimeUnit.MILLISECONDS);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">不频繁去获取锁</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">try</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #000000; ">!</span><span style="color: #000000; ">lock)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(</span><span style="color: #000000; ">60</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">catch</span><span style="color: #000000; ">&nbsp;(InterruptedException&nbsp;e)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;lock;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">boolean</span><span style="color: #000000; ">&nbsp;releaseLock(String&nbsp;key,&nbsp;String&nbsp;value)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;使用Lua脚本：先判断是否是自己设置的锁，再执行删除<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;使用lua脚本删除redis中匹配value的key，可以避免由于方法执行时间过长而redis锁自动过期失效的时候误删其他线程的锁<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;spring自带的执行脚本方法中，集群模式直接抛出不支持执行脚本的异常EvalSha&nbsp;is&nbsp;not&nbsp;supported&nbsp;in&nbsp;cluster&nbsp;environment<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;所以只能拿到原redis的connection来执行脚本</span><span style="color: #008000; "><br /></span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">String</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;keys&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;ArrayList</span><span style="color: #000000; ">&lt;&gt;</span><span style="color: #000000; ">();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;keys.add(key);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">String</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;args&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;ArrayList</span><span style="color: #000000; ">&lt;&gt;</span><span style="color: #000000; ">();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;args.add(value);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Long&nbsp;result&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(Long)redisTemplate.execute(</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;RedisCallback</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Long</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;Long&nbsp;doInRedis(RedisConnection&nbsp;connection)&nbsp;</span><span style="color: #0000FF; ">throws</span><span style="color: #000000; ">&nbsp;DataAccessException&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;nativeConnection&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;connection.getNativeConnection();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;集群模式和单机模式虽然执行脚本的方法一样，但是没有共同的接口，所以只能分开执行<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;集群模式</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(nativeConnection&nbsp;</span><span style="color: #0000FF; ">instanceof</span><span style="color: #000000; ">&nbsp;JedisCluster)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;(Long)((JedisCluster)nativeConnection).eval(UNLOCK_LUA,&nbsp;keys,&nbsp;args);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">客户端是Jedis时候(单机模式)</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(nativeConnection&nbsp;</span><span style="color: #0000FF; ">instanceof</span><span style="color: #000000; ">&nbsp;Jedis)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;(Long)((Jedis)nativeConnection).eval(UNLOCK_LUA,&nbsp;keys,&nbsp;args);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">这里使用&nbsp;redisTemplate&nbsp;中lettuce&nbsp;客户端</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DefaultRedisScript</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Long</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;redisScript&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;DefaultRedisScript</span><span style="color: #000000; ">&lt;&gt;</span><span style="color: #000000; ">();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;redisScript.setScriptText(UNLOCK_LUA);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;redisScript.setResultType(Long.</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;(Long)redisTemplate.execute(redisScript,&nbsp;keys,&nbsp;value);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">返回最终结果</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;RELEASE_SUCCESS.equals(result);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /></span></div></div><span style="color:#000080;font-weight:bold;"></span><pre style="background-color: #ffffff; color: #000000; font-family: &quot;Menlo&quot;; font-size: 11.3pt;">基于zookeeper实现下期补上：<br /><br /><br /></pre> <pre style="background-color: #ffffff; color: #000000; font-family: &quot;Menlo&quot;; font-size: 11.3pt;">介绍分布式锁文章写的比较详细：<br />https://blog.csdn.net/u010963948/article/details/79006572<br /></pre></div><div></div><div></div><div></div></div><img src ="http://www.blogjava.net/zzzlyr/aggbug/435834.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zzzlyr/" target="_blank">张钊钊</a> 2021-03-24 20:11 <a href="http://www.blogjava.net/zzzlyr/articles/435834.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JDK 8 函数式接口  Supplier、Function、Consumer、Predicate</title><link>http://www.blogjava.net/zzzlyr/articles/435611.html</link><dc:creator>张钊钊</dc:creator><author>张钊钊</author><pubDate>Fri, 24 Jul 2020 07:46:00 GMT</pubDate><guid>http://www.blogjava.net/zzzlyr/articles/435611.html</guid><wfw:comment>http://www.blogjava.net/zzzlyr/comments/435611.html</wfw:comment><comments>http://www.blogjava.net/zzzlyr/articles/435611.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zzzlyr/comments/commentRss/435611.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zzzlyr/services/trackbacks/435611.html</trackback:ping><description><![CDATA[<div><strong style="font-size: 12pt;">函数式接口的特征</strong></div>
<h3><span style="font-size: 12pt;">1、三种方法</span></h3>
<div></div>
<div>
<ul>
     <li><span style="font-size: 12pt;">唯一的抽象方法</span></li>
     <li><span style="font-size: 12pt;">使用default定义普通方法（默认方法），通过对象调用。</span></li>
     <li><span style="font-size: 12pt;">使用static定义静态方法，通过接口名调用。</span></li>
</ul>
</div>
<h3><span style="font-size: 12pt;">2、一个新注解@FunctionInterface</span></h3>
<div style="font-variant: normal; font-stretch: normal; line-height: normal; font-family: Arial;">
<ul>
     <li><span style="font-size: 12pt;">注解@FunctionalInterface告诉编译器这是一个函数式接口，明确这个函数中只有一个抽象方法，当你尝试在接口中编写多个抽象方法的时候编译器将不允许，但是可以有多个非抽象方法。</span><br />
     <br />
     </li>
     <li><span style="font-size: 12pt;">不过Object类的方法可以定义为抽象方法，因为接口的实现类一定是Object的子类</span><br />
     <br />
     </li>
     <li><span style="font-size: 12pt;">如果接口被标注了@FunctionalInterface，这个类就必须符合函数式接口的规范</span><br />
     <br />
     </li>
     <li><span style="font-size: 12pt;">即使一个接口没有标注@FunctionalInterface，如果这个接口满足函数式接口规则，依旧被当作函数式接口。</span></li>
</ul>
<h3><span style="font-size: 12pt;">3</span><span style="font-family: verdana, &quot;courier new&quot;; font-size: 12pt;">、</span><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; color: #4d4d4d; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; font-size: 12pt; font-variant-ligatures: common-ligatures; background-color: #ffffff;">JDK 1.8 新增加的函数接口包</span><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-weight: 700; overflow-wrap: break-word; color: #4d4d4d; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; font-size: 12pt; font-variant-ligatures: common-ligatures; background-color: #ffffff;">：<br />&nbsp; &nbsp;<br /></span><p><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-weight: 700; overflow-wrap: break-word; color: #4d4d4d; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; font-size: 12pt; font-variant-ligatures: common-ligatures; background-color: #ffffff;"> &nbsp;&nbsp;</span><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; color: #4d4d4d; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; font-size: 12pt; font-variant-ligatures: common-ligatures; background-color: #ffffff;"><span style="font-weight: normal;">&nbsp;&nbsp;java.util.function.*</span><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; font-weight: 400;" />&nbsp; &nbsp;&nbsp;<span style="font-weight: 400;">java.util.function 它包含了很多接口，用来支持 Java的 函数式编程，它们大致分为五类：</span><br /><br />&nbsp; &nbsp;&nbsp;<img src="http://www.blogjava.net/images/blogjava_net/zzzlyr/fu.jpg" width="1449" height="364" alt="" /><br /></span><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; color: #4d4d4d; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; font-size: 12pt; font-variant-ligatures: common-ligatures; background-color: #ffffff;">&nbsp;&nbsp;</span><span style="background-color: #ffffff; color: #4d4d4d; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; font-size: 12pt; font-variant-ligatures: common-ligatures;">&nbsp;</span></p><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word; color: #4d4d4d; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; font-size: 12pt; font-variant-ligatures: common-ligatures; background-color: #ffffff;">&nbsp;4</span>、代码样例<br /></h3><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #008000; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;<br /><div style="display: inline-block;"><div><span style="font-size: 12pt;">&nbsp; &nbsp; /**</span><br /><span style="font-size: 12pt;">&nbsp; &nbsp; &nbsp;*JDK&nbsp;8&nbsp;函数式接口&nbsp;&nbsp;Supplier、Function、Consumer、Predicate</span></div></div></span><span style="color: #008000; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<br /></span><span style="color: #008000; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; font-size: 12pt;">@param</span><span style="color: #008000; font-size: 12pt;">&nbsp;args<br /></span><span style="color: #008000; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; font-size: 12pt;">@throws</span><span style="color: #008000; font-size: 12pt;">&nbsp;Exception<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-size: 12pt;">*/</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-size: 12pt;">public</span>&nbsp;<span style="color: #0000ff; font-size: 12pt;">static</span>&nbsp;<span style="color: #0000ff; font-size: 12pt;">void</span><span style="font-size: 12pt;">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span style="color: #0000ff; font-size: 12pt;">throws</span><span style="font-size: 12pt;">&nbsp;Exception&nbsp;{</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ThreadPoolExecutor&nbsp;executor&nbsp;</span><span style="font-size: 12pt;">=</span><span style="font-size: 12pt;">&nbsp;(ThreadPoolExecutor)newFixedThreadPool(</span><span style="font-size: 12pt;">10</span><span style="font-size: 12pt;">);</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">1:JDK8以前，通过匿名内部类实现函数式接口</span><span style="color: #008000; "><br /></span><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;executor.submit(</span><span style="color: #0000ff; font-size: 12pt;">new</span><span style="font-size: 12pt;">&nbsp;Runnable()&nbsp;{</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-size: 12pt;">public</span>&nbsp;<span style="color: #0000ff; font-size: 12pt;">void</span><span style="font-size: 12pt;">&nbsp;run()&nbsp;{</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">JDK8以前，通过匿名内部类实现函数式接口</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">);</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">2:JDK8以后可以使用lambda&nbsp;表达式来实现，lambda表达式就是为了优化匿名内部类而生(分开写效果)</span><span style="color: #008000; "><br /></span><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread&nbsp;thread&nbsp;</span><span style="font-size: 12pt;">=</span>&nbsp;<span style="color: #0000ff; font-size: 12pt;">new</span><span style="font-size: 12pt;">&nbsp;Thread(()&nbsp;</span><span style="font-size: 12pt;">-&gt;</span><span style="font-size: 12pt;">&nbsp;System.out.println(</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">task&nbsp;running&nbsp;!</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">));</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Runnable&nbsp;r&nbsp;</span><span style="font-size: 12pt;">=</span><span style="font-size: 12pt;">&nbsp;()&nbsp;</span><span style="font-size: 12pt;">-&gt;</span><span style="font-size: 12pt;">&nbsp;System.out.println(</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">JDK8以后可以使用lambda&nbsp;表达式来实现，lambda表达式就是为了优化匿名内部类而生(分开写效果)!</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">);</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;executor.submit(r);</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">3:合并起来效果</span><span style="color: #008000; "><br /></span><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;executor.submit(()&nbsp;</span><span style="font-size: 12pt;">-&gt;</span><span style="font-size: 12pt;">&nbsp;{</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">JDK8以后可以使用lambda&nbsp;表达式来实现，lambda表达式就是为了优化匿名内部类而生!</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">);</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">4:其它&nbsp;Supplier、Function、Consumer、Predicate&nbsp;都可以用lambda&nbsp;表达式来实现</span><span style="color: #008000; "><br /></span><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Supplier</span><span style="font-size: 12pt;">&lt;</span><span style="font-size: 12pt;">String</span><span style="font-size: 12pt;">&gt;</span><span style="font-size: 12pt;">&nbsp;supplier&nbsp;</span><span style="font-size: 12pt;">=</span><span style="font-size: 12pt;">&nbsp;()&nbsp;</span><span style="font-size: 12pt;">-&gt;</span>&nbsp;<span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">我是SuSupplier</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">;</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Supplier</span><span style="font-size: 12pt;">&lt;</span><span style="font-size: 12pt;">Integer</span><span style="font-size: 12pt;">&gt;</span><span style="font-size: 12pt;">&nbsp;supplier2&nbsp;</span><span style="font-size: 12pt;">=</span><span style="font-size: 12pt;">&nbsp;()&nbsp;</span><span style="font-size: 12pt;">-&gt;</span>&nbsp;<span style="color: #0000ff; font-size: 12pt;">new</span><span style="font-size: 12pt;">&nbsp;Integer(</span><span style="font-size: 12pt;">1</span><span style="font-size: 12pt;">);</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">supplier=</span><span style="font-size: 12pt;">"</span>&nbsp;<span style="font-size: 12pt;">+</span><span style="font-size: 12pt;">&nbsp;supplier.get()&nbsp;</span><span style="font-size: 12pt;">+</span>&nbsp;<span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">;supplier2=</span><span style="font-size: 12pt;">"</span>&nbsp;<span style="font-size: 12pt;">+</span><span style="font-size: 12pt;">&nbsp;supplier2.get());</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">5:&nbsp;Function功能型函数式接口&nbsp;Function&lt;T,&nbsp;R&gt;&nbsp;接受一个输入参数T，返回一个结果R</span><span style="color: #008000; "><br /></span><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Function</span><span style="font-size: 12pt;">&lt;</span><span style="font-size: 12pt;">String,Integer</span><span style="font-size: 12pt;">&gt;</span><span style="font-size: 12pt;">&nbsp;function</span><span style="font-size: 12pt;">=</span><span style="font-size: 12pt;">str&nbsp;</span><span style="font-size: 12pt;">-&gt;</span><span style="font-size: 12pt;">&nbsp;Integer.parseInt(str);</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Function</span><span style="font-size: 12pt;">&lt;</span><span style="font-size: 12pt;">Integer,String</span><span style="font-size: 12pt;">&gt;</span><span style="font-size: 12pt;">&nbsp;fun2&nbsp;</span><span style="font-size: 12pt;">=</span><span style="font-size: 12pt;">&nbsp;item&nbsp;</span><span style="font-size: 12pt;">-&gt;</span><span style="font-size: 12pt;">&nbsp;item</span><span style="font-size: 12pt;">+</span><span style="font-size: 12pt;">""</span><span style="font-size: 12pt;">;</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">输入字符型&nbsp;1&nbsp;返回int型结果：</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">+</span><span style="font-size: 12pt;">function.apply(</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">1</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">));</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">输入整型&nbsp;1&nbsp;返回字符型结果：</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">+</span><span style="font-size: 12pt;">fun2.apply(</span><span style="font-size: 12pt;">2</span><span style="font-size: 12pt;">));</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">6:&nbsp;Consumer&nbsp;一个接受单个输入参数并且不返回结果的操作。&nbsp;与大多数其他函数接口不同，&nbsp;Consumer接口期望通过接受参数，改普通对象引用值(说明白点就是对原来的值进行加工，注意返回值&nbsp;void)</span><span style="color: #008000; "><br /></span><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Consumer</span><span style="font-size: 12pt;">&lt;</span><span style="font-size: 12pt;">StringBuffer</span><span style="font-size: 12pt;">&gt;</span><span style="font-size: 12pt;">&nbsp;consumer</span><span style="font-size: 12pt;">=</span><span style="font-size: 12pt;">&nbsp;sb</span><span style="font-size: 12pt;">-&gt;</span><span style="font-size: 12pt;">sb.append(</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">-yyy</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">);</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuffer&nbsp;sb1</span><span style="font-size: 12pt;">=</span><span style="color: #0000ff; font-size: 12pt;">new</span><span style="font-size: 12pt;">&nbsp;StringBuffer().append(</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">111</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">);</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;consumer.accept(sb1);</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">改变sb的内部引用值</span><span style="color: #008000; "><br /></span><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">=========s=</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">+</span><span style="font-size: 12pt;">sb1.toString());</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">7:&nbsp;Predicate&lt;T&gt;&nbsp;断言型接口常用于集合的过滤，得到一个新的集合&nbsp;Stream&nbsp;filter(Predicate&lt;?&nbsp;super&nbsp;T&gt;&nbsp;predicate);</span><span style="color: #008000; "><br /></span><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Predicate</span><span style="font-size: 12pt;">&lt;</span><span style="font-size: 12pt;">Integer</span><span style="font-size: 12pt;">&gt;</span><span style="font-size: 12pt;">&nbsp;predicate&nbsp;</span><span style="font-size: 12pt;">=</span><span style="font-size: 12pt;">&nbsp;age&nbsp;</span><span style="font-size: 12pt;">-&gt;</span><span style="font-size: 12pt;">&nbsp;age&nbsp;</span><span style="font-size: 12pt;">&gt;</span>&nbsp;<span style="font-size: 12pt;">18</span><span style="font-size: 12pt;">;</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Predicate</span><span style="font-size: 12pt;">&lt;</span><span style="font-size: 12pt;">String</span><span style="font-size: 12pt;">&gt;</span><span style="font-size: 12pt;">&nbsp;predicate2&nbsp;</span><span style="font-size: 12pt;">=</span><span style="font-size: 12pt;">&nbsp;str&nbsp;</span><span style="font-size: 12pt;">-&gt;</span><span style="font-size: 12pt;">&nbsp;str&nbsp;</span><span style="font-size: 12pt;">!=</span>&nbsp;<span style="color: #0000ff; font-size: 12pt;">null</span><span style="font-size: 12pt;">;</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(predicate.test(</span><span style="font-size: 12pt;">19</span><span style="font-size: 12pt;">));</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(predicate2.test(</span><span style="color: #0000ff; font-size: 12pt;">null</span><span style="font-size: 12pt;">));</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">我们常用集合过滤类就是对这个接口实现类&nbsp;其中&nbsp;filter(Predicate&lt;?&nbsp;super&nbsp;T&gt;&nbsp;predicate)&nbsp;用的就是这个接口</span><span style="color: #008000; "><br /></span><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List</span><span style="font-size: 12pt;">&lt;</span><span style="font-size: 12pt;">String</span><span style="font-size: 12pt;">&gt;</span><span style="font-size: 12pt;">&nbsp;list</span><span style="font-size: 12pt;">=</span><span style="font-size: 12pt;">&nbsp;Lists.newArrayList(</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">1</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">2</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">2</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">3</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">4</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">4</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">8</span><span style="font-size: 12pt;">"</span><span style="font-size: 12pt;">);</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.stream().map(s&nbsp;</span><span style="font-size: 12pt;">-&gt;</span><span style="font-size: 12pt;">&nbsp;Long.parseLong(s)).distinct().filter(s&nbsp;</span><span style="font-size: 12pt;">-&gt;</span><span style="font-size: 12pt;">&nbsp;s&nbsp;</span><span style="font-size: 12pt;">&lt;</span>&nbsp;<span style="font-size: 12pt;">10</span><span style="font-size: 12pt;">).collect(Collectors.toList()).forEach(</span><span style="font-size: 12pt;">u&nbsp;</span><span style="font-size: 12pt;">-&gt;</span><span style="font-size: 12pt;">&nbsp;System.out.println(u));</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">总结，以上的例子其实都是JDK8&nbsp;lambda&nbsp;表达式简洁的写法，而且全是合并写的，并没有分开步骤写(所有函数性接口，都可以用lambda&nbsp;表达式简洁写法)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">关闭线程池</span><span style="color: #008000; "><br /></span><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;executor.shutdownNow();</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<ul>
</ul>
</div>
<div></div><img src ="http://www.blogjava.net/zzzlyr/aggbug/435611.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zzzlyr/" target="_blank">张钊钊</a> 2020-07-24 15:46 <a href="http://www.blogjava.net/zzzlyr/articles/435611.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JDK 8 CompletableFuture 详细使用介绍</title><link>http://www.blogjava.net/zzzlyr/articles/435608.html</link><dc:creator>张钊钊</dc:creator><author>张钊钊</author><pubDate>Thu, 23 Jul 2020 11:29:00 GMT</pubDate><guid>http://www.blogjava.net/zzzlyr/articles/435608.html</guid><wfw:comment>http://www.blogjava.net/zzzlyr/comments/435608.html</wfw:comment><comments>http://www.blogjava.net/zzzlyr/articles/435608.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zzzlyr/comments/commentRss/435608.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zzzlyr/services/trackbacks/435608.html</trackback:ping><description><![CDATA[<pre><pre><br style="font-size: 14pt;" /></pre><h2><span style="font-size: 14pt;">JDK 8 中 CompletableFuture 是对 Future 的增强 大大简化了异步编程步骤,在Spring 框架中配合@EnableAsync @Async 更加事办功倍。</span></h2><span style="font-size: 14pt;">
1:在JDK 8 之前实现多线必需实现两个接口 Runnable 不带返回值，另一个Callable带返回值的接口,配合ThreadPoolTaskExecutor.submit(Callable callable) 返回一个Future对象。

使用Future获得异步执行结果时，要么调用阻塞方法get()，要么轮询看isDone()是否为true，这两种方法都不是很好，因为主线程也会被迫等待，而CompletableFuture出现改变了这个问题，而且提供更多并且强大的其它功能。<br /></span><span style="font-size: 14pt;">
2：CompletableFuture简介

CompletableFuture&lt;T&gt; implements Future&lt;T&gt;, CompletionStage&lt;T&gt;

其实CompletableFuture 除了实现原来的Future 接口外，其它大部分方法都是在CompletionStage中
<img src="https://image-static.segmentfault.com/409/022/4090228150-5d99fb9c65eb8_articlex" alt="CompletableFuture 类图" /><br /></span><span style="font-size: 14pt;">
大致介绍下completableFuture的命名规则</span><span style="font-size: 14pt;">：</span><br /><span>
</span><h3><span style="font-size: 14pt;">1:按功能分类的话：</span></h3><ul><li><code><span style="font-size: 14pt;">xxx()</span></code><span style="font-size: 14pt;">：表示该方法将继续在已有的线程中执行；</span></li><br /><li><code><span style="font-size: 14pt;">xxxAsync()</span></code><span style="font-size: 14pt;">：表示将异步在线程池中执行。</span></li><br /><li><span style="font-size: 14pt;">异步执行方法默认一个参数的话任务是在&nbsp;</span><code><span style="font-size: 14pt;">ForkJoinPool.commonPool()</span></code><span style="font-family: verdana, &quot;courier new&quot;; font-size: 14pt;">&nbsp;线程池中执行的，带executor&nbsp;参数的使用&nbsp;executor线程池异步执行。</span></li></ul><br /><h3><span style="font-size: 14pt;">2:按逻辑和组织方式来分话(completableFuture 中大约有50个来方法)</span></h3><ul><li><span style="font-size: 14pt;">一种是 then 的逻辑，即前一个计算完成的时候调度后一个计算</span></li><br /><li><span style="font-size: 14pt;">一种是 both 的逻辑，即等待两个计算都完成之后执行下一个计算，只要能组合一个和另一个，我们就可以无限复用这个 +1 的逻辑组合任意多的计算</span></li><br /><li><span style="font-size: 14pt;">另一种是 either 的逻辑，即等待两个计算的其中一个完成之后执行下一个计算。注意这样的计算可以说是非确定性的。因为被组合的两个计算中先触发下一个计算执行的那个会被作为前一个计算，而这两个前置的计算到底哪一个先完成是不可预知的</span></li></ul><h3><span style="font-size: 14pt;">3:从依赖关系和出入参数类型区别，基本分为三类：</span></h3><ul><li><span style="font-size: 14pt;">apply 字样的方式意味着组合方式是&nbsp;</span><code><span style="font-size: 14pt;">Function</span></code><span style="font-size: 14pt;">，即接受前一个计算的结果，应用函数之后返回一个新的结果</span></li><br /><li><span style="font-size: 14pt;">accept 字样的方式意味着组合方式是&nbsp;</span><code><span style="font-size: 14pt;">Consumer</span></code><span style="font-size: 14pt;">，即接受前一个计算的结果，执行消费后不返回有意义的值</span></li><br /><li><span style="font-size: 14pt;">run 字样的方式意味着组合方式是&nbsp;</span><code><span style="font-size: 14pt;">Runnable</span></code><span style="font-family: verdana, &quot;courier new&quot;; font-size: 14pt;">，即忽略前一个计算的结果，仅等待它完成后执行动作</span></li></ul><span style="font-size: 14pt;">其中出入参数主要有JDK8 Function，Consumer或Runnable三中函数型接口,每一种都决定了是怎么样一种依赖关系,我有一篇文章详细介绍了JDK8函数型接口用法，能有助理解completableFuture方法使用。</span><br /><a href="http://www.blogjava.net/zzzlyr/articles/435611.html"><span style="font-size: 14pt;">http://www.blogjava.net/zzzlyr/articles/435611.html</span></a><br /><pre><h3><span style="font-size: 14pt;">4:completableFuture 配合框架使用</span></h3><pre><span style="font-size: 14pt;">  因为自从JDK8以后增强了多线程的使用便捷程度：</span><br /><span style="font-size: 14pt;">  1：JDk8 的函数式接口和lambda表过式</span><br /><span style="font-size: 14pt;">  2：completableFuture 对 Future 类的增强。</span><br /><span style="font-size: 14pt;"> 这只是JDK 基础包中的功能，现在大部分开发都在使用框架 java 现在基本上都在使用spring框架，因为JDK基础包中的功能还是不如框架使用方便，下边文章详细介绍 springboot中对JDK基础包中多线程功能配置和使用。 </span><br /></pre><a href="http://www.blogjava.net/zzzlyr/articles/435305.html"><span style="font-size: 14pt;">http://www.blogjava.net/zzzlyr/articles/435305.html</span></a><br />
<pre><br /></pre>
</pre>
<pre><br />
</pre>
<pre><br />
</pre>
</pre><img src ="http://www.blogjava.net/zzzlyr/aggbug/435608.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zzzlyr/" target="_blank">张钊钊</a> 2020-07-23 19:29 <a href="http://www.blogjava.net/zzzlyr/articles/435608.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SpringBoot异步及线程池配置(jdk8新增加线程支持CompletableFuture)</title><link>http://www.blogjava.net/zzzlyr/articles/435305.html</link><dc:creator>张钊钊</dc:creator><author>张钊钊</author><pubDate>Wed, 25 Mar 2020 12:19:00 GMT</pubDate><guid>http://www.blogjava.net/zzzlyr/articles/435305.html</guid><wfw:comment>http://www.blogjava.net/zzzlyr/comments/435305.html</wfw:comment><comments>http://www.blogjava.net/zzzlyr/articles/435305.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zzzlyr/comments/commentRss/435305.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zzzlyr/services/trackbacks/435305.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 如何在 Spring 使用@Async,@EnableAsync注释进行异步处理:异步处理适用那些与业务逻辑（横切关注点）不直接相关或者不作为其他业务逻辑输入的部分，也可在分布式系统中解耦。*译注：横切关注点（cross-cutting concerns）指一些具有横越多个模块的行为，使用传统的软件开发方法不能够达到有效模块化的一类特殊关注点。*Spring 中，`@Async`注解可以标记异步操...&nbsp;&nbsp;<a href='http://www.blogjava.net/zzzlyr/articles/435305.html'>阅读全文</a><img src ="http://www.blogjava.net/zzzlyr/aggbug/435305.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zzzlyr/" target="_blank">张钊钊</a> 2020-03-25 20:19 <a href="http://www.blogjava.net/zzzlyr/articles/435305.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA 泛型总结！</title><link>http://www.blogjava.net/zzzlyr/articles/424765.html</link><dc:creator>张钊钊</dc:creator><author>张钊钊</author><pubDate>Wed, 29 Apr 2015 10:18:00 GMT</pubDate><guid>http://www.blogjava.net/zzzlyr/articles/424765.html</guid><wfw:comment>http://www.blogjava.net/zzzlyr/comments/424765.html</wfw:comment><comments>http://www.blogjava.net/zzzlyr/articles/424765.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zzzlyr/comments/commentRss/424765.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zzzlyr/services/trackbacks/424765.html</trackback:ping><description><![CDATA[<div></div>
<p style="line-height:150%"><span style="font-size: 18pt; line-height: 150%; font-family: Verdana, sans-serif;">1</span><span style="font-size: 18pt; line-height: 150%; font-family: 宋体;">：今天偶尔想起了泛型，都快忘记了在次总结下！</span><span style="font-size: 18pt; line-height: 150%; font-family: Verdana, sans-serif;"><br /> </span>JAVA <span style="font-size: 18pt; line-height: 150%; font-family: 宋体;">泛型分为：泛型类，泛型接口，泛型方法，泛型继承；</span><span style="font-size: 18pt; line-height: 150%; font-family: Verdana, sans-serif;"><br /> </span>泛型还可以限制参数类型的上下限等<span style="font-size: 18pt; line-height: 150%; font-family: Verdana, sans-serif;"><br /> </span>1<span style="font-size: 18pt; line-height: 150%; font-family: 宋体;">：自定义类泛型</span><span style="font-size: 18pt; line-height: 150%; font-family: Verdana, sans-serif;"><br /> </span>public class GenericTest&lt;T&gt;<br /> 2: <span style="font-size: 18pt; line-height: 150%; font-family: 宋体;">泛型接口</span><span style="font-size: 18pt; line-height: 150%; font-family: Verdana, sans-serif;">(</span><span style="font-size: 18pt; line-height: 150%; font-family: 宋体;">也可以自定义</span><span style="font-size: 18pt; line-height: 150%; font-family: Verdana, sans-serif;">)</span><span style="font-size: 18pt; line-height: 150%; font-family: 宋体;">，泛型继承</span><span style="font-size: 18pt; line-height: 150%; font-family: Verdana, sans-serif;"><br /> </span>public interface List&lt;E&gt; extends Collection&lt;E&gt;&nbsp;<br /> 3<span style="font-size: 18pt; line-height: 150%; font-family: 宋体;">：泛型方法</span><span style="font-size: 18pt; line-height: 150%; font-family: Verdana, sans-serif;"><br /> </span>public &lt;T&gt; List&lt;T&gt; getListBykey(String key, Class&lt;?&gt; T)<br /> 4<span style="font-size: 18pt; line-height: 150%; font-family: 宋体;">：泛型限制参数类型上下限（例泛型类型只能是</span><span style="font-size: 18pt; line-height: 150%; font-family: Verdana, sans-serif;">String </span><span style="font-size: 18pt; line-height: 150%; font-family: 宋体;">类和子类）</span><span style="font-size: 18pt; line-height: 150%; font-family: Verdana, sans-serif;"><br /> </span>上限<span style="font-size: 18pt; line-height: 150%; font-family: Verdana, sans-serif;"><br /> </span>public class GenericTest&lt;?extends String&gt;&nbsp;<br /> 下限：<span style="font-size: 18pt; line-height: 150%; font-family: Verdana, sans-serif;"><br /> </span>public class GenericTest&lt;? super &nbsp;String&gt; &nbsp;<br /> 其中<span style="font-size: 18pt; line-height: 150%; font-family: Verdana, sans-serif;">?</span><span style="font-size: 18pt; line-height: 150%; font-family: 宋体;">是通配符，代表任意类型</span></p>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div><img src ="http://www.blogjava.net/zzzlyr/aggbug/424765.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zzzlyr/" target="_blank">张钊钊</a> 2015-04-29 18:18 <a href="http://www.blogjava.net/zzzlyr/articles/424765.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>