首页
归档
留言
友链
广告合作
壁纸
更多
美女主播
Search
1
博瑞GE车机升级/降级
5,607 阅读
2
Mac打印机设置黑白打印
4,934 阅读
3
修改elementUI中el-table树形结构图标
4,894 阅读
4
Mac客户端添加腾讯企业邮箱方法
4,672 阅读
5
intelliJ Idea 2022.2.X破解
4,354 阅读
后端开发
HarmonyOS Next
Web前端
微信开发
开发辅助
App开发
数据库
随笔日记
登录
/
注册
Search
标签搜索
Spring Boot
Java
Vue
Spring Cloud
Mac
MyBatis
WordPress
MacOS
asp.net
Element UI
Nacos
.Net
Spring Cloud Alibaba
MySQL
Mybatis-Plus
Typecho
jQuery
Java Script
IntelliJ IDEA
微信小程序
Laughing
累计撰写
627
篇文章
累计收到
1,421
条评论
首页
栏目
后端开发
HarmonyOS Next
Web前端
微信开发
开发辅助
App开发
数据库
随笔日记
页面
归档
留言
友链
广告合作
壁纸
美女主播
搜索到
627
篇与
的结果
2022-10-23
使用CompletableFuture<T>实现异步接口
【同步API】同步API是我们传统方法,调用方法在被调用方法运行的过程中会一直等待,直到被调用方法返回。此时的调用过程,是阻塞式的调用。【异步API】与同步API相反,异步API会直接返回,或者至少在被调用方计算完成之前,将它剩余的计算任务交给另外一个线程去做,该线程和调用方是异步的,是非阻塞式调用。来看一下【同步API】与【异步API】的区别 public class Shop { public double getPrice(String product) { return calculatePrice(product); } public Future<Double> getPriceAsync(String product) { CompletableFuture<Double> futurePrice = new CompletableFuture<>(); new Thread(() -> { double price = calculatePrice(product); futurePrice.complete(price); }).start(); return futurePrice; } private double calculatePrice(String product) { delay(); return new Random().nextDouble() * product.charAt(0) * product.charAt(1); } public static void delay() { try { Thread.sleep(1000L); } catch (InterruptedException interruptedException) { throw new RuntimeException(interruptedException); } } } 在上面的代码中,getPrice()是一个同步方法,其内部调用的calculatePrice()用于模拟价格计算,计算过程中,暂停线程1s用于模拟阻塞。然后我们调用getPrice(),查看程序执行时间。 public class Main { public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException { Shop shop = new Shop(); long startTime = System.currentTimeMillis(); double doubleFuture = shop.getPrice("apple"); doSomeThingElse(); long endTime = System.currentTimeMillis(); System.out.println("总耗时:" + (endTime - startTime) + "ms"); } private static void doSomeThingElse(){ try { Thread.sleep(2000L); } catch (InterruptedException e) { e.printStackTrace(); } } } 此时查看控制台,我们可以看到共执行了3011ms,也就是说,此时整个程序是串行的。此时我们再来看看另一个方法getPriceAsync(),此方法不再返回double类型,而是一个Future<Double>,Future<T>接口标识一个异步计算的结果,泛型代表返回值。Future的计算结果,通过get()方法获取。在getPriceAsync()方法中,我们创建了一个代表异步计算的CompletableFuture<T>,它在计算完成后,会包含计算的结果。接着创建一个线程去执行实际的操作,不必等到线程结束,直接返回一个Future<Double>实例。当线程计算结束后,调用CompletableFuture<T>的complete()方法,结束CompletableFuture<T>的运行。然后我们调用getPriceAsync()方法,查看程序执行时间。public class Main { public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException { Shop shop = new Shop(); long startTime = System.currentTimeMillis(); Future<Double> doubleFuture = shop.getPriceAsync("apple"); doSomeThingElse(); doubleFuture.get(2, TimeUnit.SECONDS); long endTime = System.currentTimeMillis(); System.out.println("总耗时:" + (endTime - startTime) + "ms"); } private static void doSomeThingElse(){ try { Thread.sleep(2000L); } catch (InterruptedException e) { e.printStackTrace(); } } }此时查看控制台,可以看到总体耗时2108ms,也就是说我们主程序跟getPriceAsync()方法此时是并行的了。【改进的异步方法】在前面的getPriceAsync()方法中,我们创建了一个线程创建CompletableFuture<T>对象,实际上,还有一种更简便的方式,即使用工厂方法CompletableFuture.supplyAsync创建CompletableFuture<T>对象。改进后的代码如下所示 public Future<Double> getPriceAsync(String product) { // CompletableFuture<Double> futurePrice = new CompletableFuture<>(); // new Thread(() -> { // double price = calculatePrice(product); // futurePrice.complete(price); // }).start(); // return futurePrice; return CompletableFuture.supplyAsync(()-> calculatePrice(product)); }
2022年10月23日
833 阅读
0 评论
1 点赞
2022-10-20
MySQL数据库外键和索引等名称的长度限制
Identifier TypeMaximum Length (characters)Database64 (NDB storage engine: 63)Table64 (NDB storage engine: 63)Column64Index64Constraint64Stored Program64View64Tablespace64Server64Log File Group64Alias256 (see exception following table)Compound Statement Label16
2022年10月20日
729 阅读
0 评论
1 点赞
2022-10-12
Java BigDecimal Non-terminating decimal expansion; no exact representable decimal result
在日常开发中,我们基本上都是用BigDecimal类型来处理金额,防止精度丢失。使用BigDecimal做除法时,如果出现除不尽的情况,系统就会报错之所以出现这个问题,是因为除法除不尽时,BigDecimal不知道如何处理了,因此,使用BigDecimal做除法时,我们需要指定结果的精度及四舍五入的方式。BigDecimal bigDecimalThree = new BigDecimal("3"); BigDecimal newBigDecimal = BigDecimal.ONE.divide(bigDecimalThree, 1, RoundingMode.HALF_EVEN); System.out.println(newBigDecimal);
2022年10月12日
945 阅读
0 评论
0 点赞
2022-10-03
java8函数式接口注解FunctionalInterface
函数式接口就是为Java 8的Lambda表达式准备的,Java 8允许使用Lambda表达式创建函数式接口的实例,因此Java 8 专门增加了@FunctionalInterface。什么是函数式接口我们提到如果接口中只有一个抽象方法(可以包含多个默认方法或多个 static 方法),那么该接口就是函数式接口。FunctionalInterface作用@FunctionalInterface就是用来指定某个接口必须是函数式接口,所以@FunInterface只能修饰接口,不能修饰其它程序元素。看下一下面的方法@FunctionalInterface public interface BufferedReaderProcessor { /** * 静态方法 */ static void process() { System.out.println("process"); } /** * 抽象方法 * * @param bufferedReader * @return * @throws IOException */ String process(BufferedReader bufferedReader) throws IOException; /** * 默认方法 * * @param bufferedReader * @return * @throws IOException */ default String process1(BufferedReader bufferedReader) throws IOException { return ""; } }此时IDE是没有任何错误的(当然代码没有错误)截止到此时,我们出程序中的@FunctionalInterface一丢丢的作用,其实@FunctionalInterface注解的作用只是告诉IDE检查这个接口,保证该接口只能包含一个抽象方法,否则就会编译出错。如何理解一个抽象方法的含义。是否能只不包含抽象方法?我们继续修改刚才的代码,注释掉唯一的一个抽象方法 @FunctionalInterface public interface BufferedReaderProcessor { /** * 静态方法 */ static void process() { System.out.println("process"); } // /** // * 抽象方法 // * // * @param bufferedReader // * @return // * @throws IOException // */ // String process(BufferedReader bufferedReader) throws IOException; /** * 默认方法 * * @param bufferedReader * @return * @throws IOException */ default String process1(BufferedReader bufferedReader) throws IOException { return ""; } }此时,IDE给了错误提示了:No target method found(没有找到目标方法),也就是说,一旦使用@FunctionalInterface注解接口,我们必须要提供一个抽象方法。是否能提供多个抽象方法?刚刚我们看到了,一旦接口@FunctionalInterface,我们接口必须包含抽象方法,那么是否能包含多个抽象方法呢,我们看下面代码。@FunctionalInterface public interface BufferedReaderProcessor { /** * 静态方法 */ static void process() { System.out.println("process"); } /** * 抽象方法 * * @param bufferedReader * @return * @throws IOException */ String process(BufferedReader bufferedReader) throws IOException; /** * 抽象方法 * * @return */ String process1(); /** * 默认方法 * * @param bufferedReader * @return * @throws IOException */ default String process1(BufferedReader bufferedReader) throws IOException { return ""; } }此时ide提示Multiple non-overriding abstract methods found in XXX(找到多个非重载的抽象方法),也就是说,一个接口一旦注解了@FunctionalInterface就只能有一个抽象方法。
2022年10月03日
1,239 阅读
0 评论
3 点赞
2022-10-01
docsify常用的一些插件及配置
前面的几篇文章,我们陆续介绍了docsify网站的搭建及一些基本配置。本篇是我们关于docsify系列介绍的最后一篇。主要介绍一下我们常用的一些docsify插件。docsify的配置其实就是一些js及css插件,因此我们下面凡是脚本,大家都放到body中,凡是css文件,都放到head中,配置文件统一放到docsify配置节点。有不会配置的可以参考https://lisen.cc/blog/the-docsify-configuration-article-navigation.html一、统计文章字数1.1、添加插件<!-- 字数插件 --> <script src="//cdn.jsdelivr.net/npm/docsify-count@latest/dist/countable.min.js"></script>1.2、配置// 字数插件 count: { countable: true, position: 'top', margin: '10px', float: 'left', fontsize: '0.9em', color: 'rgb(90,90,90)', language: 'chinese', localization: { words: "", minute: "" }, isExpected: true },二、支持翻页1.1、添加插件<!-- 翻页 --> <script src="//cdn.jsdelivr.net/npm/docsify-pagination/dist/docsify-pagination.min.js"></script>1.2、配置pagination: { previousText: '上一章节', nextText: '下一章节', crossChapter: true, crossChapterText: true, },三、图片放大缩小点击图片可以查看大图。 <!-- 图片放大缩小支持 --> <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/zoom-image.min.js"></script>四、emoji表情支持 <!-- emoji表情支持 --> <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/emoji.min.js"></script>五、点击复制所有的代码块上添加一个简单的Click to copy按钮来允许用户从你的文档中轻易地复制代码。 <!--在所有的代码块上添加一个简单的Click to copy按钮来允许用户从你的文档中轻易地复制代码--> <script src="//cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script>六、美化提示 <!-- 美化提示 --> <script src="//cdn.jsdelivr.net/npm/docsify-plugin-flexible-alerts"></script>具体使用方式可以参考https://www.npmjs.com/package/docsify-plugin-flexible-alerts
2022年10月01日
2,845 阅读
0 评论
1 点赞
2022-09-30
docsify配置文章内导航
当我们一篇文章比较长时,有个文章内导航可能帮助读者快速的定位到文章对应的章节,比如,我们下面这个测试文章,每个导航,只能不停的滚动鼠标。docsify配置文章内导航,只需一个插件便可解决。一、添加插件1.1、添加脚本文件在body中添加脚本文件<!-- 文章内导航 --> <script src="//cdn.jsdelivr.net/npm/docsify-toc@1.0.0/dist/toc.js"></script>1.2、添加样式在body中添加样式文件<!-- 文章内导航 --> <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify-toc@1.0.0/dist/toc.css">这样,我们在查看文章时,文章就会有一个导航栏了。个性化配置默认的配置可能并不满足我们的需要,那么我们可以对导航栏进行一些个性化配置。在docsify配置文件中,添加如下内容 toc: { scope: '.markdown-section', headings: 'h1, h2, h3, h4, h5, h6', title: '导航', },再次打开文章页面,可以查看一下效果
2022年09月30日
1,613 阅读
2 评论
1 点赞
2022-09-30
docsify配置查询功能
在前面的几篇文章中,我们介绍了docsify配置封面、导航栏、侧边栏等信息。其实一个基本的网站框架基本已经搭建起来了,但是现在还有一个问题,如果我们文章比较多的时候,寻找其他就比较麻烦,因此我们需要一个查询功能,以便能快速定位到我们需要的内容。添加搜索插件在index.html中添加搜索插件 <!-- 搜索功能支持 --> <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>添加完搜索插件之后,我们网站左上角其实已经有了搜索框,但是现在的搜索框是不易用的,比如提示信息还是英文等等。配置搜索功能在docsify配置文件中,添加以下内容search: { maxAge: 3600000,// 过期时间,单位毫秒,默认一天 paths: 'auto',// 注意:仅适用于 paths: 'auto' 模式 placeholder: '搜索', // 支持本地化 placeholder: { '/zh-cn/': '搜索', '/': '搜索' }, noData: '找不到结果', depth: 4, hideOtherSidebarContent: false, namespace: '香草物语', sidebarDisplayLevel: 1, },
2022年09月30日
1,351 阅读
0 评论
0 点赞
2022-09-29
docsify配置导航栏
在docsify配置侧边栏中,我们介绍了配置侧边栏的方法,其实配置导航栏的方式跟配置侧边栏是类似的。配置docsify在index.html中配置docsify,支持导航栏。 <script> window.$docsify = { name: '', repo: '', //启用封面支持 coverpage:true, //支持导航栏 loadNavbar: true, // 侧边栏支持,默认加载的是项目根目录下的_sidebar.md文件 loadSidebar: true, // 最大支持渲染的标题层级 maxLevel: 5, // 自定义侧边栏后默认不会再生成目录,设置生成目录的最大层级(建议配置为2-4) subMaxLevel: 4, } </script>添加侧边栏配置文件启用导航栏之后,我们需要添加一个导航栏配置文件_navbar.md。在根目录下创建文件_navbar.md创建完成后,目录结构如下然后我们根据需要配置导航栏 * 香草物语 * [后端开发](https://lisen.cc/category/back/) * [Web前端](https://lisen.cc/category/web/)效果如下
2022年09月29日
1,511 阅读
0 评论
1 点赞
2022-09-28
docsify配置侧边栏
docsify配置完成后,默认显示的是README.md的内容,侧边栏显示的就是README.md的目录。比如我的README.md配置# 李森的博客 > https://lisen.cc # 我是一级目录 ## 我是二级目录 但是我们的在线文档一般不会只有一个文件,我们更多的是像文件夹层级一样,按照文件夹的目录展示我们的文档,所以,我们可以将MarkDown文件,然后所在文件夹级次进行展示。配置docsify在index.html中配置docsify,支持侧边栏。 window.$docsify = { name: '', repo: '', //启用封面支持 coverpage:true, // 侧边栏支持,默认加载的是项目根目录下的_sidebar.md文件 loadSidebar: true, // 最大支持渲染的标题层级 maxLevel: 5, // 自定义侧边栏后默认不会再生成目录,设置生成目录的最大层级(建议配置为2-4) subMaxLevel: 4, }添加侧边栏配置文件如果只配置上面,启用侧边栏支持,你会发现左侧侧边栏没有了,此时,我们需要添加一个侧边栏配置文件_sidebar.md。在根目录下创建文件_sidebar.md在_sidebar.md中配置文件目录* 我是一级目录一 * [我是二级目录1.1](/文章/我是一级目录一/我是二级目录1.1.md) <!--注意这里是相对路径--> * [我是二级目录1.1](/文章/我是一级目录一/我是二级目录1.2.md) * 我是一级目录二 * [我是二级目录2.1](/文章/我是一级目录二/我是二级目录2.1.md)然后根据我们_sidebar.md中配置的目录,创建对应文件或文件夹配置完成后,再次预览我们的网站
2022年09月28日
2,077 阅读
0 评论
2 点赞
2022-09-24
typecho替换QQ头像
前言Typecho使用的是Gravatar作为用户的头像,但是大部分用户都没有设置Gravatar头像,而且Gravatar在国内访问速度感人,大大影响了用户体验和站点速度。解决方法让数字QQ邮箱显示QQ头像,非数字QQ邮箱使用Gravatar国内镜像加快速度。修改文件在typecho根目录/var/Typecho/Common.php文件,注释掉大约在第1010行至第1028行的代码/** public static function gravatarUrl($mail, $size, $rating, $default, $isSecure = false) { …… return $url; }**/在其下方添加以下 php 代码public static function gravatarUrl($mail, $size, $rating, $default, $isSecure = false) { $reg = "/^\d{5,11}@[qQ][Qq]\.(com)$/"; if (preg_match($reg, $mail)) { $img = explode("@", $mail); $url = "//q2.qlogo.cn/headimg_dl?dst_uin={$img[0]}&spec=100"; } else { if (defined('__TYPECHO_GRAVATAR_PREFIX__')) { $url = __TYPECHO_GRAVATAR_PREFIX__; } else { $url = $isSecure ? 'https://gravatar.loli.net' : 'http://gravatar.loli.net'; $url .= '/avatar/'; } if (!empty($mail)) { $url .= md5(strtolower(trim($mail))); } $url .= '?s=' . $size; $url .= '&r=' . $rating; $url .= '&d=' . $default; } return $url; } 现在Typecho全局支持数字QQ邮箱显示QQ头像了,Gravatar使用国内镜像源。{message type="info" content="我的文件格式化了,所以显示行数可能不太一样,主要看方法名吧。"/}
2022年09月24日
1,790 阅读
1 评论
4 点赞
2022-09-24
Typecho修改首页文章数量
{mtitle title="需求"/}默认typecho首页只显示5篇文章。对于部分主题确实已经足够,但是双栏的主题5篇文章会显得过少。其实就像我的网站,5篇文章显然是不够的,所以我需要调整到10篇。但是typecho并没有提供前端的修改方法,我们需要修改数据库达到目的。{mtitle title="修改方法"/}打开数据库,找到typecho_options数据表中的项pageSize将其修改为所需数量即可。比如我需要显示10篇,直接改成10就行了。
2022年09月24日
1,387 阅读
0 评论
1 点赞
2022-09-24
docsify配置LaTeX公式
MarkDown本身是支持LaTeX公式的,但是docsify默认是不支持LaTeX公式的,即便你输入了如下的公式$$ 现值 = 原值/(1+折现率)^{(到期日-折现日期间隔月份)/12} $$ docsify也只会给你显示原始的内容。 要实现公式的显示,我们可以通过以下方式。方式一、贴图 我们可以使用typora这种软件,显示MarkDown内容,然后截图粘贴到docsify对应的文件中,当然,这种方式能把自己蠢哭。方式二、通过插件 docsify-katex就是能显示LaTeX公式的一种插件,使用方式非常简单。 将样式文件粘贴到head中,并将js文件粘贴到body中。<!-- 公式 --> <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/katex@latest/dist/katex.min.css" /><!-- 公式 --> <script src="//cdn.jsdelivr.net/npm/katex@latest/dist/katex.min.js"></script> <script src="//cdn.jsdelivr.net/npm/marked@4"></script> <script src="//cdn.jsdelivr.net/npm/docsify-katex@latest/dist/docsify-katex.js"></script>{message type="error" content="注意脚本文件的引入顺序。"/}
2022年09月24日
2,555 阅读
2 评论
6 点赞
1
...
13
14
15
...
53