精华内容
下载资源
问答
  • ![图片说明]... 浏览器自带的打印 自己分割的把字分割成两半了, 如何能块状打印 一个模块一个模块 因为我内容是渲染好的 或者能把字打印全 因为填充内容一样有的多有的少 页面会被拉伸
  • 线程池中的一个线程异常了会被怎么处理? 估计很多人会是以下三点答案(me too): 1.抛异常出来并打印在控制台上 2.其他线程任务不受影响 3.异常线程会被回收 但是这里我先提前说一下以上三点不全对,下面我们来具体...

    线程池中的一个线程异常了会被怎么处理?

    估计很多人会是以下三点答案(me too):

    1.抛异常出来并打印在控制台上

    2.其他线程任务不受影响

    3.异常线程会被回收

    但是这里我先提前说一下以上三点不全对,下面我们来具体分析一下。

    话不多说用代码来证明

    熟悉Executors线程池(本文线程池都是指Executors)都知道 有两种提交线程的方式execute和submit方式,下面将以这两种提交方式来验证。

    贴个代码凑个数

    public static void main(String[] args) {
    ThreadPoolTaskExecutor executorService = buildThreadPoolTaskExecutor();
    executorService.execute(() -> run("execute方法"));
    executorService.submit(() -> run("submit方法"));
    }
    
    private static void run(String name) {
    String printStr = "【thread-name:" + Thread.currentThread().getName() + ",执行方式:" + name+"】";
    System.out.println(printStr);
    throw new RuntimeException(printStr + ",出现异常");
    }
    
    private static ThreadPoolTaskExecutor buildThreadPoolTaskExecutor() {
    ThreadPoolTaskExecutor executorService = new ThreadPoolTaskExecutor();
    executorService.setThreadNamePrefix("(小罗技术笔记)-");
    executorService.setCorePoolSize(5);
    executorService.setMaxPoolSize(10);
    executorService.setQueueCapacity(100);
    executorService.setKeepAliveSeconds(10);
    executorService.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    executorService.initialize();
    return executorService;
    }
    

    20200425001.png

    观看执行结果,诶好奇怪

    execute执行方式抛出异常显示在控制台了。

    submit执行方式啥都没有输出。

    众所周知submit底层其实也是调用的execute,因此它也有异常只是处理方法不一样,它们的区别是:

    1、execute没有返回值。可以执行任务,但无法判断任务是否成功完成。——实现Runnable接口

    2、submit返回一个future。可以用这个future来判断任务是否成功完成。——实现Callable接口

    那怎么拿到submit中的异常呢?还是用代码来说话

    Future<?> result=executorService.submit(() -> run("submit方法"));
    try {
    result.get();
    }catch (Exception e){
    e.printStackTrace();
    }
    

    20200425002.jpg

    获取了一下submit方法的返回结果,发现有异常了和execute一样了,所以第一点抛异常出来并打印在控制台上不是全对的!

    到这估计大家和我一样都有一个疑问了 ,为啥execute直接抛出异常,submit没有呢?

    要知道这个答案就只能去翻源码看了

    在java.util.concurrent.ThreadPoolExecutor#runWorker中抛出了运行异常:
    20200425003.png

    在java.lang.ThreadGroup#uncaughtException进行了异常处理:
    20200425004.png

    uncaughtException是什么,我也不知道,百度了一下说这个方法是JVM调用的,在线程中只需要指定我们想要的处理方式即可
    20200425005.png

    说道这里你可能会吐槽说了这么多submit到底为啥没有直接抛出异常,到底是怎么处理了,不要慌我们再看源码找答案
    20200425006.png

    看submit源码会发现,submit中传进来的task会被封装成一个FutureTask,然后再调用execute,最后返回FutureTask。
    20200425007.png

    你会发现走的是execute方法,如下图,会发现此时的task已经是FutureTask,所以再去看一下FutureTask的run方法是咋写的。
    20200425008.png

    异常被存起来了…,再看源码是怎么实现的
    20200425009.png

    返回参数里面有一个状态state翻源码发现在report方法中同时用到outcom和state状态判断打个断点发现还真是,当state为3时抛出了异常。
    20200425010.png

    同理在找寻一下report调用位置可以很明显发现是FutureTask中get方法调用了,结合上面可以很明确了submit提交时异常被存储在线程结果信息中,当调用get方法是判断线程运行结果状态,有异常就抛出存储的异常信息,因此submit运行异常我们只能用get方法来拿到。

    至于第二点我就不多说了,平时使用中就已经证明了!

    第三点线程出异常了不是被线程池回收嘛?

    看源码我们知道线程运行最后总有一个processWorkerExit要执行,看看里面的实现

    20200425011.png

    很神奇先删掉线程又再调用创建线程的方法,所以异常线程不是被回收,而是被删除了再创建一个新的顶替了。

    到此线程池中的线程异常了会被怎么处理讲完了,总结一下就是:

    1、execute方法,可以看异常输出在控制台,而submit在控制台没有直接输出,必须调用Future.get()方法时,可以捕获到异常。

    2、一个线程出现异常不会影响线程池里面其他线程的正常执行。

    3、线程不是被回收而是线程池把这个线程移除掉,同时创建一个新的线程放到线程池中。

    4、还有源码是个好东西,答案都在里面,就是太难看懂了

    xuanchuantu.png

    展开全文
  • 先看一个最简单的打印System.out.println(newObject()); 会输出该类的限定类名和一串字符串:java.lang.Object@6659c656 @符号后面的...

    先看一个最简单的打印

    System.out.println(new Object());
    

    会输出该类的全限定类名和一串字符串:

    java.lang.Object@6659c656
    

    @符号后面的是什么?是 hashcode 还是对象的内存地址?还是其他的什么值?

    其实@后面的只是对象的 hashcode 值,16进制展示的 hashcode 而已,来验证一下:

    Object o = new Object();
    int hashcode = o.hashCode();
    // toString
    System.out.println(o);
    // hashcode 十六进制
    System.out.println(Integer.toHexString(hashcode));
    // hashcode
    System.out.println(hashcode);
    // 这个方法,也是获取对象的 hashcode;不过和 Object.hashcode 不同的是,该方法会无视重写的hashcode
    System.out.println(System.identityHashCode(o));
    

    输出结果:

    java.lang.Object@6659c656
    6659c656
    1717159510
    1717159510
    

    那对象的 hashcode 到底是怎么生成的呢?真的就是内存地址吗?

    本文内容基于 JAVA 8 HotSpot

    hashCode 的生成逻辑

    JVM 里生成 hashCode 的逻辑并没有那么简单,它提供了好几种策略,每种策略的生成结果都不同。

    来看一下 openjdk 源码里生成 hashCode 的 核心方法:

    static inline intptr_t get_next_hash(Thread * Self, oop obj) {
      intptr_t value = 0 ;
      if (hashCode == 0) {
         // This form uses an unguarded global Park-Miller RNG,
         // so it's possible for two threads to race and generate the same RNG.
         // On MP system we'll have lots of RW access to a global, so the
         // mechanism induces lots of coherency traffic.
         value = os::random() ;
      } else
      if (hashCode == 1) {
         // This variation has the property of being stable (idempotent)
         // between STW operations.  This can be useful in some of the 1-0
         // synchronization schemes.
         intptr_t addrBits = intptr_t(obj) >> 3 ;
         value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;
      } else
      if (hashCode == 2) {
         value = 1 ;            // for sensitivity testing
      } else
      if (hashCode == 3) {
         value = ++GVars.hcSequence ;
      } else
      if (hashCode == 4) {
         value = intptr_t(obj) ;
      } else {
         // Marsaglia's xor-shift scheme with thread-specific state
         // This is probably the best overall implementation -- we'll
         // likely make this the default in future releases.
         unsigned t = Self->_hashStateX ;
         t ^= (t << 11) ;
         Self->_hashStateX = Self->_hashStateY ;
         Self->_hashStateY = Self->_hashStateZ ;
         Self->_hashStateZ = Self->_hashStateW ;
         unsigned v = Self->_hashStateW ;
         v = (v ^ (v >> 19)) ^ (t ^ (t >> 8)) ;
         Self->_hashStateW = v ;
         value = v ;
      }
    
      value &= markOopDesc::hash_mask;
      if (value == 0) value = 0xBAD ;
      assert (value != markOopDesc::no_hash, "invariant") ;
      TEVENT (hashCode: GENERATE) ;
      return value;
    }
    

    从源码里可以发现,生成策略是由一个 hashCode 的全局变量控制的,默认为5;而这个变量的定义在另一个头文件里:

      product(intx, hashCode, 5,                                            
             "(Unstable) select hashCode generation algorithm" ) 
    

    源码里很清楚了……(非稳定)选择 hashCode 生成的算法,而且这里的定义,是可以由 jvm 启动参数来控制的,先来确认下默认值:

    java -XX:+PrintFlagsFinal -version | grep hashCode
    
    intx hashCode                                  = 5                                   {product}
    openjdk version "1.8.0_282"
    OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_282-b08)
    OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.282-b08, mixed mode)
    

    所以我们可以通过 jvm 的启动参数来配置不同的 hashcode 生成算法,测试不同算法下的生成结果:

    -XX:hashCode=N
    

    现在来看看,每种 hashcode 生成算法的不同表现。

    第 0 种算法

    if (hashCode == 0) {
         // This form uses an unguarded global Park-Miller RNG,
         // so it's possible for two threads to race and generate the same RNG.
         // On MP system we'll have lots of RW access to a global, so the
         // mechanism induces lots of coherency traffic.
         value = os::random();
      }
    

    这种生成算法,使用的一种Park-Miller RNG的随机数生成策略。不过需要注意的是……这个随机算法在高并发的时候会出现自旋等待

    第 1 种算法

    if (hashCode == 1) {
        // This variation has the property of being stable (idempotent)
        // between STW operations.  This can be useful in some of the 1-0
        // synchronization schemes.
        intptr_t addrBits = intptr_t(obj) >> 3 ;
        value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;
    }
    

    这个算法,真的是对象的内存地址了,直接获取对象的 intptr_t 类型指针

    第 2 种算法

    if (hashCode == 2) {
        value = 1 ;            // for sensitivity testing
    }
    

    这个就不用解释了……固定返回 1,应该是用于内部的测试场景。

    有兴趣的同学,可以试试-XX:hashCode=2来开启这个算法,看看 hashCode 结果是不是都变成 1 了。

    第 3 种算法

    if (hashCode == 3) {
        value = ++GVars.hcSequence ;
    }
    

    这个算法也很简单,自增嘛,所有对象的 hashCode 都使用这一个自增变量。来试试效果:

    System.out.println(new Object());
    System.out.println(new Object());
    System.out.println(new Object());
    System.out.println(new Object());
    System.out.println(new Object());
    System.out.println(new Object());
    
    //output
    java.lang.Object@144
    java.lang.Object@145
    java.lang.Object@146
    java.lang.Object@147
    java.lang.Object@148
    java.lang.Object@149
    

    果然是自增的……有点意思

    第 4 种算法

    if (hashCode == 4) {
        value = intptr_t(obj) ;
    }
    

    这里和第 1 种算法其实区别不大,都是返回对象地址,只是第 1 种算法是一个变体。

    第 5 种算法

    最后一种,也是默认的生成算法,hashCode 配置不等于 0/1/2/3/4 时使用该算法:

    else {
         // Marsaglia's xor-shift scheme with thread-specific state
         // This is probably the best overall implementation -- we'll
         // likely make this the default in future releases.
         unsigned t = Self->_hashStateX ;
         t ^= (t << 11) ;
         Self->_hashStateX = Self->_hashStateY ;
         Self->_hashStateY = Self->_hashStateZ ;
         Self->_hashStateZ = Self->_hashStateW ;
         unsigned v = Self->_hashStateW ;
         v = (v ^ (v >> 19)) ^ (t ^ (t >> 8)) ;
         Self->_hashStateW = v ;
         value = v ;
      }
    

    这里是通过当前状态值进行异或(XOR)运算得到的一个 hash 值,相比前面的自增算法和随机算法来说效率更高,但重复率应该也会相对增高,不过 hashCode 重复又有什么关系呢……

    本来 jvm 就不保证这个值一定不重复,像 HashMap 里的链地址法就是解决 hash 冲突用的

    总结

    hashCode 可以是内存地址,也可以不是内存地址,甚至可以是 1 这个常数或者自增数!想用什么算法,它都可以!

    源于 | juejin.cn/post/6961229793056686117

    展开全文
  • 项目采用SpringMVC+Mybatis的...然后开始看Mybatis的官方文档,关于日志这一块是怎么处理的 最近Mybatis有中文文档了,虽然不全,不过已经很好了,这里面发现了项目中存在的问题。项目中引入了shiro框架,集成了...

    项目采用SpringMVC+Mybatis的架构,日志工具还是最常用的log4j,整合了其他框架之后,发现无法打印SQL语句,然而项目中的显示调用日志却可以正常打印出来,还有当SQL拼写有错误的时候会打印出来

    然后开始看Mybatis的官方文档,关于日志这一块是怎么处理的

    最近Mybatis有中文文档了,虽然不全,不过已经很好了,这里面发现了项目中存在的问题。项目中引入了shiro框架,集成了slf4j日志,导致了Mybatis无法引用log4j的配置文件打印SQL语句

    问题原因:这个是Mybatis默认查找日志的顺序,自上而下,也就是说,如果项目中有前面3个日志框架时,对于Mybatis,log4j就不会生效

    • SLF4J
    • Apache Commons Logging
    • Log4j 2
    • Log4j
    • JDK logging

     

    解决办法在MyBatis的配置文件mybatis-config.xml里面添加一项setting来指定log4j

     

    [html] view plain copy

    1. <configuration>    
    2.     <settings>    
    3.         <setting name="logImpl" value="LOG4J" />      
    4.     </settings>    
    5. </configuration>  


    log4j中对指定内容进行输出,其中example为包名,可以继续细化处理

     

    [html] view plain copy

    1. log4j.logger.example=DEBUG  


    至此问题解决

    展开全文
  • 对于一些打印的字符的处理 用那个函数可将个位数前面的零值显示出来? 如果你要在A3的前面插入100行 请问如何每隔30行粘贴一新行 在工作表里有连续10行数据, 现在要每行间格2行 一个大表每一行下面需要加一行空行...
  • LINUX与UNIX SHELL编程指南(很)

    热门讨论 2009-07-26 17:30:33
    非常的,绝对不会让你后悔。 目 录 译者序 前言 第一部分 shell 第1章 文件安全与权限 1 1.1 文件 1 1.2 文件类型 2 1.3 权限 2 1.4 改变权限位 4 1.4.1 符号模式 4 1.4.2 chmod命令举例 5 1.4.3 绝对模式 5 ...
  • ========= 上面的程序不知哪里有问题,于是我就又优化了一下,代码如下,但遇到大数据还是读出来=================== public class SocketService { private static Socket socket; private ...
  • 今天在Hyperf里做切片上传的时候看到以前的代码是从接口把整个切片内容读出来到微服务中处理 这样不仅造成微服务间通信的高达几M的数据交互,也会造成无法调取微服务的问题 说了上代码 我遇到的问题是前端传...

    今天在Hyperf里做切片上传的时候看到以前的代码是从接口把整个切片内容读出来到微服务中处理

    这样不仅造成微服务间通信的高达几M的数据交互,也会造成无法调取微服务的问题

    不说了上代码

    我遇到的问题是前端传了三片文件,第三片无法访问微服务

    在调取微服务的时候直接报错,这是怎么回事呢?

    打印下切片内容

    第一,第二片很正常,第三片全是“”

    如果没猜错的话就是这个问题

    所以我们把file_get_contents()拿到微服务里执行。传递的参数只是临时路径tmp

    这样就解决了这个问题、

    展开全文
  • 因为硬件兼容的问题,可能打印口的并口模式与“软件狗”兼容,所以可以进入COMS 系统调整打印口的并口模式; 判断“软件狗”是否坏掉,有条件可在另一台机器上安装一套《管家婆》试运行;如仍然能运行《管家婆...
  • 1.15 老板永远打不开的Word! 35 1.16 PDF可以完整地转换为Word吗? 36 1.17 Word遇到问题还得找Word! 38 Chapter2 排版流程:这样做才专业! 39 2.1 排版流程:了解科学排版的过程 40 2.2 样式:Word排版工程...
  • 【超golang面试题合集+golang学习指南+golang知识图谱+成长路线】 一份涵盖大部分golang程序员所需要掌握的核心知识。 脑图持续不断更新中,在线查看地址 后续文章和内容会不断更新到 github项目 中,...
  • 你必须知道的495个C语言问题

    千次下载 热门讨论 2015-05-08 11:09:25
    打印出49。不管按什么顺序计算,难道该是56吗? 3.3 对于代码inti=3;i=i++;不同编译器给出不同的i值,有的为3,有的为4,哪个是正确的? *3.4 有这样一个巧妙的表达式:a^=b^=a^=b;它需要临时变量就可以交换...
  • 8 、你可以选择按照什么原则对源文本进行分段,就是说,源文本中怎么确定 哪些行是同一段的。是按照源文本中的空行,还是按照设定的一些行末字符,例如 ‘。’、‘!’等等,或者两者同时使用。 9 、是否矫正段内...
  • 不管按什么顺序计算, 难道打印出56吗? o 4.3 对于代码 int i = 3; i = i++; 不同编译器给出不同的结果, 有的为 3, 有的为 4, 哪个是正确的? o 4.4 这是个巧妙的表达式: a ^= b ^= a ^= b 它需要临时变量就...
  • 11群是四个群中最小的群,其中继计次表位于缓冲区的首位,完电话后查询内存发现出中继群号在内存中是正确的,取完话单后再查就正确了。 结 论: 话单池的一个备份指针Pool_head_1和中继计次表的头指针重合,...
  • 打印出49。不管按什么顺序计算,难道该是56吗? 33  3.3 对于代码int i=3; i=i++; 不同编译器给出不同的i值,有的为3,有的为4,哪个是正确的? 34  *3.4 有这样一个巧妙的表达式:a^= b^= a^= b; 它需要...
  • 《你必须知道的495个C语言问题》

    热门讨论 2010-03-20 16:41:18
    打印出49。不管按什么顺序计算,难道该是56吗? 33  3.3 对于代码int i=3; i=i++; 不同编译器给出不同的i值,有的为3,有的为4,哪个是正确的? 34  *3.4 有这样一个巧妙的表达式:a^= b^= a^= b; 它需要...
  • 如果需要更精确的说法,\b匹配这样的位置:它的前一个字符和后一个字符不全是(一个是,一个不是或不存在)\w。 假如你要找的是hi后面不远处跟着一个Lucy,你应该用\bhi\b.*\bLucy\b。 这里,.是另一个元字符,匹配除了...
  • 数据库.txt

    2019-10-19 23:14:32
    在使用它时,只需要发出"做什么"的命令,"怎么做"是不用使用者考虑的。 SQL功能强大、简单易学、使用方便,已经成为了数据库操作的基础,并且现在几乎所有的数据库均支持SQL。 <1> 在数据库系统中,SQL语句区分...
  • 在使用它时,只需要发出"做什么"的命令,"怎么做"是不用使用者考虑的。 SQL功能强大、简单易学、使用方便,已经成为了数据库操作的基础,并且现在几乎所有的数据库均支持SQL。 <1> 在数据库系统中,SQL语句区分...
  • VC++常用功能实例

    2010-01-25 23:28:46
    问:视口的活动性如何处理? 70 问:如何使用COleClientItem的IDispatch接口? 70 问:关于用户自定义的消息使用? 71 问:在打开一个文档时退出? 71 问:在CListCtrl控件中多选择项的删除? 71 问:工作线程的登录...
  • 软件工程教程

    热门讨论 2012-07-06 23:10:29
    用例只描述参与者和系统在交互过程中做些什么,并描述怎么做。 用例图 关联关系 用例图 泛化关系 用例图 泛化关系 用例图 用例图 用例图 用例用于什么情况? 知道什么情况不用用例 如果没有用到用例,...
  • 问:视口的活动性如何处理? 70 问:如何使用COleClientItem的IDispatch接口? 70 问:关于用户自定义的消息使用? 71 问:在打开一个文档时退出? 71 问:在CListCtrl控件中多选择项的删除? 71 问:工作线程的登录...

空空如也

空空如也

1 2 3 4
收藏数 66
精华内容 26
关键字:

打印打不全怎么处理