范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

谈谈代码JavaIO业务代码优化之路Java开发实战

  版本
  日期
  备注
  1.0
  2019.4.27
  文章首发
  1.1
  2021.6.10
  修改标题:从一段代码谈起——浅谈JavaIO接口-> 谈谈代码:Java IO业务代码优化之路1.前言
  前阵子休息天日常在寻找项目里不好的代码,看到了这样的一段代码:    private Result sshSameExec(Session session, String cmd) {         if (log.isDebugEnabled()) {             log.debug("shell command: {}", cmd);         }         UserInfo ui = getUserInfo();         session.setUserInfo(ui);         int exitStatus = 0;         StringBuilder builder = new StringBuilder();         ChannelExec channel;         InputStream in;         InputStream err;         try {             session.connect(connectTimeout);             channel = (ChannelExec) session.openChannel("exec");             channel.setCommand(cmd);             in = channel.getInputStream();             err = channel.getErrStream();             channel.connect();         } catch (Exception e) {             throw new CloudRuntimeException(e);         }          try {             long lastRead = Long.MAX_VALUE;             byte[] tmp = new byte[1024];             while (true) {                 while (in.available() > 0 || err.available() > 0) {                     int i = 0;                     if (in.available() > 0) {                         i = in.read(tmp, 0, 1024);                     } else if (err.available() > 0) {                         i = err.read(tmp, 0, 1024);                     }                     if (i < 0) {                         break;                     }                     lastRead = System.currentTimeMillis();                     builder.append(new String(tmp, 0, i));                 }                 if (channel.isClosed()) {                     if (in.available() > 0) {                         continue;                     }                     exitStatus = channel.getExitStatus();                     break;                 }                 if (System.currentTimeMillis() - lastRead > exeTimeout) {                     break;                 }             }         } catch (IOException e) {             throw new CloudRuntimeException(e);         } finally {             channel.disconnect();             session.disconnect();         }          if (0 != exitStatus) {             return Result.createByError(ErrorData.builder()                     .errorCode(ResultCode.EXECUTE_SSH_FAIL.getCode())                     .detail(builder.toString())                     .title(ResultCode.EXECUTE_SSH_FAIL.toString())                     .build());         } else {             return Result.createBySuccess(builder.toString());         }     }
  简单解释一下这段代码——即通过ssh到一台机器上,然后执行一些命令.对命令输出的东西,开了一个循环,每一次读一定的位置,然后以字节流的形式读回来.
  这段代码有点丑,于是我闻到了学习的味道.
  首先是对两个Stream的消费,很显然,在多核环境下,我们同时也只能够消费其中一个Stream.其次,这代码太挫了,自己定义一个tmp,然后1024、1024这样的去取出来.
  在改良之前,我们先来回顾一下JavaIO的接口定义.2.JavaIO 接口知识回顾2.1 低级抽象接口:InputStream 和 OutputStream
  这里有同学可能问了,为啥叫它低抽象接口呢?因为它离底层太近了,计算机本来就是处理二进制的,而这两个接口正是用来处理二进制数据流的.
  先简单看一眼这两个接口:InputStream**  * This abstract class is the superclass of all classes representing  * an input stream of bytes.  *  * 

Applications that need to define a subclass of InputStream * must always provide a method that returns the next byte of input. * * @author Arthur van Hoff * @see java.io.BufferedInputStream * @see java.io.ByteArrayInputStream * @see java.io.DataInputStream * @see java.io.FilterInputStream * @see java.io.InputStream#read() * @see java.io.OutputStream * @see java.io.PushbackInputStream * @since JDK1.0 */ public abstract class InputStream implements Closeable {.....}OutputStream/** * This abstract class is the superclass of all classes representing * an output stream of bytes. An output stream accepts output bytes * and sends them to some sink. *

* Applications that need to define a subclass of * OutputStream must always provide at least a method * that writes one byte of output. * * @author Arthur van Hoff * @see java.io.BufferedOutputStream * @see java.io.ByteArrayOutputStream * @see java.io.DataOutputStream * @see java.io.FilterOutputStream * @see java.io.InputStream * @see java.io.OutputStream#write(int) * @since JDK1.0 */ public abstract class OutputStream implements Closeable, Flushable {...}   我们可以发现,它们都实现了Closeable的接口.因此大家在使用这些原生类时,要注意在结束时调用Close方法哦.   这两个接口的常用实现类有: - FileInputStream和FileOutputStreamDataInputStream和DataOutputStream ObjectInputStream和ObjectOutputStream2.2 高级抽象接口——Writer和Reader   为啥说它是高级抽象接口呢?我们先来看看它们的注释:Writer/** * Abstract class for writing to character streams. The only methods that a * subclass must implement are write(char[], int, int), flush(), and close(). * Most subclasses, however, will override some of the methods defined here in * order to provide higher efficiency, additional functionality, or both. * * @see Writer * @see BufferedWriter * @see CharArrayWriter * @see FilterWriter * @see OutputStreamWriter * @see FileWriter * @see PipedWriter * @see PrintWriter * @see StringWriter * @see Reader * * @author Mark Reinhold * @since JDK1.1 */ public abstract class Writer implements Appendable, Closeable, Flushable {Reader/** * Abstract class for reading character streams. The only methods that a * subclass must implement are read(char[], int, int) and close(). Most * subclasses, however, will override some of the methods defined here in order * to provide higher efficiency, additional functionality, or both. * * * @see BufferedReader * @see LineNumberReader * @see CharArrayReader * @see InputStreamReader * @see FileReader * @see FilterReader * @see PushbackReader * @see PipedReader * @see StringReader * @see Writer * * @author Mark Reinhold * @since JDK1.1 */ public abstract class Reader implements Readable, Closeable {   我们可以看到,这个抽象类是用来面向character的,也就是字符.字符的抽象等级必然比字节高,因为字符靠近上层,即人类.2.3 优化输入和输出——Buffered   如果我们直接使用上述实现类去打开一个文件(如FileWriter 、FileReader 、FileInputStream 、FileOutputStream ),对其对象调用read、write、readLine等,每个请求都是由基础OS直接处理的,这会使一个程序效率低得多——因为它们都会引发磁盘访问or网络请求等.   为了减少这种开销,Java 平台实现缓冲 I/O 流。缓冲输入流从被称为缓冲区(buffer)的存储器区域读出数据;仅当缓冲区是空时,本地输入 API 才被调用。同样,缓冲输出流,将数据写入到缓存区,只有当缓冲区已满才调用本机输出 API。   用于包装非缓存流的缓冲流类有4个:BufferedInputStream和BufferedOutputStream·用于创建字节缓冲字节流, BufferedReader和BufferedWriter`用于创建字符缓冲字节流.3. 着手优化   之前,我们提到了这段代码写得搓的地方:首先是对两个Stream的消费,很显然,在多核环境下,我们同时也只能够消费其中一个Stream.其次,这代码太挫了,自己定义一个tmp,然后1024、1024这样的去取出来.   故此,我们可以考虑对每个Stream都进行包装,支持用线程去消费,其次我们可以用高级抽象分接口去适配Byte,然后去装饰成Buffer.   接下来,我们来看一段ZStack里的工具类ShellUtils,为了节省篇幅,我们仅仅截出它在IDE里的Structure:   run方法的核心:   我们可以看到StreamConsumer这个类,我们来看一下它的代码: private static class StreamConsumer extends Thread { final InputStream in; final PrintWriter out; final boolean flush; StreamConsumer(InputStream in, PrintWriter out, boolean flushEveryWrite) { this.in = in; this.out = out; flush = flushEveryWrite; } @Override public void run() { BufferedReader br = null; try { br = new BufferedReader(new InputStreamReader(in)); String line; while ( (line = br.readLine()) != null) { out.println(line); if (flush) { out.flush(); } } } catch (Exception e) { logger.warn(e.getMessage(), e); } finally { try { if (br != null) { br.close(); } } catch (IOException e) { logger.warn(e.getMessage(), e); } } } }   这段代码已经达到了我们的理想状态:线程消费,高级抽象.3.1 使用Kotlin3.1.1 Kotlin IO   闲话不多说,先贴代码为敬:import java.io.InputStream import java.io.InputStreamReader class StreamGobbler(private val inputStream: InputStream, private var result: StringBuilder) : Runnable { override fun run() { InputStreamReader(inputStream).buffered().use { it.lines().forEach { r -> result.append(r) } } } }   还是一样熟悉的配方,我们逐行来解读:定义一个类,并且要求构造函数必须传入InputStream和一个StringBuilder.且实现了Runnable接口,这意味着它可以被线程消费.覆写run方法.我们可以看到InputStream被适配成了InputStreamReader,这意味着它可以输出字符流了,然后我们使用了Kotlin的接口将其装饰成了Buffer.读每一行buffer,并appned到result这个StringBuilder里去.读完就可以告辞了,close.(use会将其关闭)3.1.2 Kotlin Coroutine   先看一下上面的图,我们都知道内核态线程是由OS调度的,但当一个线程拿到时间片时,却调到了阻塞IO,那么只能等在那边,浪费时间.   而协程则可以解决这个问题,当一个Jobhang住的时候,可以去做别的事情,绕开阻塞.更好的利用时间片.   最后,我们来看一下成品代码: override fun sshExecWithCoroutine(session: Session, cmd: String): SimpleResult { val ui = InnerUserInfo() session.userInfo = ui val exitStatus: Int var channel = ChannelExec() val inputBuilder = StringBuilder() val errorBuilder = StringBuilder() try { session.connect(connectTimeout) channel = session.openChannel("exec") as ChannelExec channel.setCommand(cmd) channel.connect() val inputStream = StreamGobbler(channel.inputStream, inputBuilder) val errStream = StreamGobbler(channel.errStream, errorBuilder) val customJob = GlobalScope.launch { customStream(inputStream, errStream) } while (!customJob.isCompleted) { // wait job be done } exitStatus = channel.exitStatus } catch (e: IOException) { throw java.lang.RuntimeException(e) } finally { if (channel.isConnected) { channel.disconnect() } if (session.isConnected) { session.disconnect() } } return if (0 != exitStatus) { return SimpleResult.createByError(ErrorData.Builder() .errorCode(ResultCode.EXECUTE_SSH_FAIL.value) .detail(errorBuilder.toString()) .title(ResultCode.EXECUTE_SSH_FAIL.toString()) .build()) } else { SimpleResult.createBySuccess(inputBuilder.toString()) } } private suspend fun customStream(inputStream: StreamGobbler, errorStream: StreamGobbler) { val inputDeferred = GlobalScope.async { inputStream.run() } val errorDeferred = GlobalScope.async { errorStream.run() } inputDeferred.join() errorDeferred.join() }   作者:泊浮目   链接:https://juejin.cn/post/6971215096282513416


vivoX70Pro上手体验一部可以让人爱上摄影的高端旗舰与光学大厂合作,已成为当前手机厂商在提升手机影像算法图片成像效果方面的主要方式之一。其中vivo与光学巨头蔡司的合作一直备受业内关注,vivo旗下的X系列更是成为其冲击影像旗舰的代中兴MyOS上手体验中兴Axon30最后一块短板,补齐了智能手机三大件屏幕处理器和系统。得其一者,可立足也得其二者,跻身一线三者兼备,执牛耳指日可待。举例来说苹果拥有最顶级的屏幕(及显示优化能力)自研A系列处理器以及独家iOS系统,从而平时就刷个微信,看看新闻,不玩游戏,买什么手机比较好?只是用微信和新闻客户端的话,容量稍大的百元机足够了。就个人使用过的红米4A来说,浏览新闻和使用微信的时候,动画谈不上丝滑,但也不会明显卡顿。性能完全不用担心。微信需要很多的存储空间互联网公司,求求你别把我当年轻人了有的年轻人看着炫酷潮帅,光鲜亮丽,但手机一掏,App一开,大字却赫然在眼前。你若追问,他也不会脸露难色,只会跟你淡淡地说一句挺好使的,比标准版好用多了。多新鲜啊,越来越多年轻人正用iPhone不能禁售吗?苹果的麻烦事来了,这次我国企业的态度很强硬老美对我国的高科技领域设置了重重障碍,一直以来就有人问,为什么我们不对美企对等实施反制措施?老话说不是不报,时候未到!苹果公司这次遇到大难题了!1中企向苹果索赔100亿!就在苹果公夜晚喜欢拍照啥的,vivoX70Pro这部手机影像如何?感谢您的阅读!夜晚喜欢拍照啥的,vivoX70Pro这部手机影像如何?前一段时间,我们看到人民日报,对于vivoX70Pro进行了褒奖,特别提到了这一款手机支持V1芯片,这是viv有没有那种性价比高,能玩原神8128的1500左右的手机?文小伊评科技原神作为目前主流游戏中最吃性能的游戏之一,想要玩好这个游戏,就必须要保证手机中CPU和GPU性能,而手机性能的决定性因素就是处理器的性能(内存容量为8128G起步即可,风冷手持便携激光焊接机你了解吗?1500风冷手持激光焊机是基于自主产权的风冷976nm高效节能技术高亮度单模组激光器技术,内嵌激光焊接工艺软件,为国内首款千瓦级风冷激光智能焊机,正式步入激光焊机的千亿市场新赛道。搬运工人形机器人诞生,未来将是人工智能的世界从终结者到西部世界,机器人的故事一直是科幻小说的主题。这些电影提出了关于道德劳动和人类控制我们所创造技术的能力的重要问题。现在,类人型机器人比以往任何时候都更接近成为社会结构的一部阴谋?华为黑粉为什么突然变得这么多?前几天苹果刚发布iPhone13的时候,写了一篇文章苹果新机iPhone13很强,但先看看需要多少玉米?再决定要不要购买文章这篇文章完全是因为iPhone13刚发布,所以用了iPh中国特斯拉取消6个月超级免费充电引荐奖励,美国也不例外中华网财经9月18日讯,有细心网友发现特斯拉从今天起正式取消车主引荐奖励计划。根据特斯拉官网公告显示,从9月18日起将不再提供引荐奖励。车主引荐奖励是老用户向亲友推荐特斯拉汽车,亲
iPhone上满屏的小红点,逼死了多少强迫症?是日机哥约八弟出去玩。到他楼下后打了个电话喊他,结果等了10分钟,他才气喘吁吁下来。我问他下个楼而已,为什么花这么长时间。八弟说他一下楼,就怀疑自己刚才没锁门。来回跑了几趟,才心满关机拔卡,就能保住行程码吗?由于近期国内疫情范围的扩大,不止苏州,还有很多地方都越来越关注每个人的行程码而非健康码。光是抱紧你的小绿码已经不够了,还要保住你的行程码不带。可是对每天在本地固定场所上班的人来说不国产机里也有高端,这四款很难挑出毛病,还比苹果便宜我们购买一部手机要遵循一个原则,那就是首先确定预算,然后在预算范围之内根据自己的需求选择手机,切不可根据需求再确定预算。在生活中有一种现象很常见,厂商发布了一款新手机,你很喜欢,于今天市场的一些信息作者明野数据支持勾股大数据(www。gogudata。com)大家好,今天简单说下互联网和地产互联网主要是阿里的回购,250亿美金,差不多等于阿里十分之一的市值了,金额中概股第一,卷完钱就跑路?万门大学疑似倒闭创始人逃往日本3月22日消息,不少网友发现,今日著名学习平台万门大学VIP群把自己踢出,App无法使用,AppStore也搜索不到万门大学了。从目前的情况来看,万门大学很有可能倒闭了,中新经纬甚中央空调和分体式空调我都知道,风管机是什么鬼?能装在家里吗?过去装空调,我们连想都不用想,几乎只有一种选项分体式空调,也就是一个室内机,用管道连接着一个室外机的那种。后来中央空调走下神坛,开始面向家庭用户,于是家里又出现了中央空调这个选项。预算1500以内,买一款性价比高的千元机,荣耀X30值得考虑预算1500以内想要买一款性价比高的手机,荣耀X30值得考虑,这款手机是荣耀公司于2021年底上市的新机,是一款可以媲美旗舰体验的千元机,亮点是骁龙6nm疾速5G芯66W超级快充1买小家电别只认美的海尔,这4个小众品牌就不错,功能强大又便宜生活中有一些小家电可以提升生活幸福感,虽然有些人感觉他们比较鸡肋,买了会吃灰,但是真正等拥有的时候就会知道,原来他们的功能这么强大,拥有之后生活真的越来越顺心。虽然买家电的时候小品目前屏幕素质最强的四款手机,不建议你错过目前屏幕素质最强的四款手机推荐!远离低素质劣屏。第一款iQOO9Pro采用了一块6。78英寸的三星AMOLED柔性直屏,支持2K分辨率,支持LTPO无级变速2。0,在畅享120Hz元宇宙调查报告(3)元宇宙骤然成为全球话题,随之而来的则是各种媒体上与元宇宙相关概念的井喷限量NFT(非同质化代币)收藏品虚拟地产炒房万亿美元新市场在元宇宙正在成为新的现实的当下,这个来源于30年前科实测一匹空调26度,开一晚上其实真的很省电空调的主要用途还是制冷,特别是夏季,现在的空调都会有26度的标识,这个温度值还是比较舒适的。大品牌一匹的变频空调,室外温度35度左右,开一晚上按8小时计算,10几平米的卧室,通过功