Marchen的博客

分享一切喜欢的事物


  • 首页

  • 标签

  • 分类

  • 归档

  • 关于

  • 日程表

内存溢出问题排查(spring jpa缓存溢出)

发表于 2020-06-23

1.问题和思路

      在最近的项目中遇到一个非常棘手的问题,系统在使用一段时间之后,就会直接down掉,经过排查error日志,发现了内存溢出的报错,报错如下:

阅读全文 »

Kafka实战

发表于 2020-05-18 | 分类于 技术

      在未接触kafka实际的场景时,我一直以为他只是一个

相关概念

  1. broker
          broker在这里相当于一个安装了kafka的服务器,kafka集群模式时需要在sever.properties中配置broker.id属性,在集群模式中,borker.id不能一样,否则会出现问题。
  2. topic(主题)
          topic类似于rabbitmq的queue,用于存放消息。kafka没有像rabbitmq一样,存在exchange、bindingKey、routingKey等,仅使用topic来接受消息和存放消息,消息以文件格式存在服务器的磁盘中,可以设置保存的时间,因此kafka有时也可以作为数据库来保存数据。
  3. partition(分区)
          patition(分区)是kafka不同于其它几个消息中间件的地方,分区是消息存储的最小的概念,一个topic可以有一个或多个分区,分区的数量可以在创建topic的时候进行配置。
  4. producer
          kafka作为一个消息中间件,必然会存在生产者和消费者,
  5. consumerGroup
  6. consumer

身未动,心仪远--深圳

发表于 2019-08-31 | 分类于 旅行

        2019年7月31日,我终于踏上了飞往深圳的航班,虽然今天深圳的天气由于台风的影响晚点了将近4个小时,但一点也没有打消掉我对去深圳的那份激动的心情。至于为什么会这么想去深圳呢? 可能是因为那里有一群待宰的小肥羊(如上图所示,一群一直喊着只要我去深圳就要带我吃遍深圳美食的大学同学)。哈哈哈,小肥羊,你们的狼叔叔就要来了(哇哦……)

阅读全文 »

身未动,心仪远--南京

发表于 2019-06-23 | 分类于 旅行
阅读全文 »

spring Boot之Environment

发表于 2019-06-22 | 分类于 技术

      Spring Boot是现在实现微服务最基础,最受欢迎的一个Spring开发框架,其本身拥有Spring的全部功能,并且提供了很多特性和功能来简化开发人员的开发,深受喜欢,我也是其忠实粉丝之一。

      如果你问我你为什么会喜欢使用这个框架,我不会告诉你它有如下的优势,我会喜欢看着你写着一大堆的XML配置,哈哈哈……。

Spring Boot优势

  • 大量的自动配置,开发人员不需要配置一大堆的XML模版文件,简化开发。
  • 内嵌的Servlet服务器,不需要部署Web应用时还需要部署Tomcat、Jetty等应用服务器才能使用。
  • 提供了大量的启动依赖,开发人员不需要考虑版本冲突,依赖相关问题。
  • 提供了Spring actuator等组件,便于监控和管理应用信息。
  • 其本身可以和Spring Cloud等框架完美结合,不需要过多的配置等。
阅读全文 »

线程池使用与实现原理

发表于 2019-05-27 | 分类于 技术

    线程池在日常的开发中占据着非常的重要作用,即便我们在日常的开发中没有使用过线程池,也肯定听过周边的开发人员提到过过线程池这个东西。那么,线程池到底是用来做什么?为了解决什么问题呢?

前言

    在之前的博客(Synchronized和lock详解)中提到过,线程是最小的运算逻辑单元,合理的使用线程可以充分的利用资源,提升运行的效率,但是使用大量的线程也有相应的缺点。

  • 创建线程和创建普通对象一样,会消耗内存,运行结束后也需要回收资源,因此,在创造大量线程的时候,可能会造成OOM或者应用崩溃。举个例子,如果我们网页请求的时候,对于每个请求创建一个线程,某一刻来了成千上万个请求,就有可能造成OOM。
  • 创建大量的线程不利于管理,每个线程拥有各自的名字,查找问题的时候,可能会花费很长时间找不到问题的具体所在。

    为了防止出现上述问题,国内著名公司阿里巴巴的编程规范就要求,对于使用到线程创建的都应该使用到线程池,而且应使用ThreadPoolExecutor来进行线程池的创建,至于为什么需要使用ThreadPoolExecutor来创建,这个我们之后在详细说明。阿里巴巴公司的编码规范要求必须使用线程池创建和管理线程,足以说明了线程池的重要性,所以使用和掌握线程池很重要。接下来,我会从总体到细致的方式,来共同学习线程池。

阅读全文 »

Synchronized和lock详解

发表于 2019-05-13

      线程是最小的运算逻辑单元,合理的使用线程可以充分利用CPU资源,线程之间采用堆内存的方式进行交互,多个线程之间共享堆内存,但这会存在一个问题,如果不合理的使用线程,就会导致代码执行的安全性和准确性。那么Java是如何解决呢?

阅读全文 »

问题汇总

发表于 2019-05-08 | 分类于 技术
  1. 什么会造成线程死锁?如何解决?
    造成原因:

    • 互斥条件:即多个线程在某一个时间内都需要获取相同资源
    • 请求与保持条件:即一个线程因请求资源而阻塞时,对自身已获得的资源不会释放
    • 不剥夺条件:在一个线程未执行完任务之前,不能剥夺它已获得资源
    • 循环等待条件: 多个线程形成一种循环等待相应资源的关系。
      在多线程开发中,如果一个线程X持有资源A的锁,需要获得资源B的锁,而线程Y持有资源B的锁,需要获得资源A的锁,此时便会发生死锁的情况。
      解决:
      只需要打破上述4个条件中的某一个就会打破死锁。
  2. 红黑树是什么?请说明下特点和实现原理?

  3. 什么是TCP协议的三次握手,做了什么?为什么不能使用两次握手协议?
    答:TCP协议是TCP可靠性实现的基础和保证。

    • 当客户端需要发消息给服务端时,客户端首先会发送给服务端一个消息、消息头中的SYN标志,seq=x给服务端;
    • 服务端收到客户端发送的消息之后,检查如果是一个消息头如果有SYN=1,则返回给客户端SYN, ACK标志,以及返回给客户端seq=y和ack=x+1;
    • 客户端收到服务端的确认消息之后,检查消息头中是否含有ACK标志,如果含有则返回ACK标,以及返回给服务端seq=x+1和ack=y+1。
      三次握手协议保证了传输的可靠性,如果是两次握手协议,某一刻客户端发送的消息在网络中滞留了,客户端没有收到服务端发送的消息,会继续发送消息给服务端,服务端收到了该消息并给予确认。如果采用的是两次握手,则滞留的消息到服务端后,服务端又会重新建立连接,而客户端会忽略该消息,从而导致服务端的连接浪费。
  4. 如何实现多个线程满足某个条件时继续往下执行?CyclicBarrier和CountdownLatch的区别是什么?
    答:实现多个线程满足条件继续执行可以采用java.util.councurrent包下的CyclicBarrier和CountdownLatch类。

    • CountDownLatch是一个任务等待其他任务执行完成之后才执行,内部主要使用队列同步器(AQS)实现,实现了其中的tryAcquireShared(int arg)和tryReleaseShared(int arg)方法实现;只能使用一次
    • CyclicBarrier是一组线程等待某个状态后再全部同时执行,内部使用可重入锁和条件变量实现,当调用await()方法时,会加锁然后判断是否count为0,若为0,则唤醒所有的线程,否则进入自循环来进行阻塞等待。
    • 信号量,信号量可以控制访问某资源的线程数,通过acquire()和release()来获取访问资源以及释放访问资源。内部也是采用队列同步器(AQS)实现,并且实现了公平获取信号和非公平获取。
  5. JVM启动参数你都知道哪些?说明下是干什么用的?
    答:JVM启动参数分之为三类:标准参数、非标准参数和非Stable参数

    • 标准参数:

      -verbose:class 输出JVM载入类的相关信息,当报异常
      -verbose:gc 输出每次GC的相关信息
      -verbose:jni 输出native方法调用的相关情况,一般用于诊断jni调用的错误信息

    • 非标准参数:

      -Xms256M 设置堆内存的大小
      -Xmx1024M 设置堆的最大内存的大小
      -Xms128M 设置新生代的大小
      -Xss1M 设置每个线程的堆栈大小

    • 非Stable参数:

      命令及参数 描述
      -XX:-DisableExplicitGC 禁用System.gc()
      -XX:-UseConcMarkSweepGC 对老年代采用并发标记算法进行GC
      -XX:-UseParallelGC 启用并行GC
      -XX:-UseSerialGC 启用串行GC
      -XX:MaxNewSize=size 设置新生代内存的最大值
      -XX:MaxPermSize=size 设置永久代占用内存的最大值
      -XX:NewRation=2 设置新生代和老年代的比例
      -XX:ErrorFile=XXX.log 保存错误日志到文件中
      -XX:HeapDumpPath=XXX.hprof 指定导出堆信息时的路径
      -XX:-HeapDumpOutOfMemoryError 指定导出堆信息时的路径
      -XX:-PrintGC 输出GC的相关信息
      -XX:-PrintDC Details 输出GC的详细信息
      -XX:-PrintGCTimeStamps 输出每次GC的时间戳
  6. Cookie、Session、Token的区别是什么?

  7. Java内存泄露造成的原因是什么?怎么排查与解决?
    答:内存泄露造成的原因包含两个条件:泄露对象到GC Root拥有有向图,从而造成虚拟机GC时不能回收对象;二是该对象是无用对象。
    排查:

    • 首先通过jps 命令查看java是哪个进程
    • 通过jstate -gcutil vmid time count查看内存的占比情况
    • 通过jmap -histo:live vmid或jmap -dump:live,format=b,file=xxx.hprof命令输出某一刻的堆栈的情况,查看占用内存比较大的对象,进行合理分析。
    • 如果不能够判断出代码问题出现在什么地方?可以通过ma(memory analyiz)分析工具分析下是哪块代码造成,然后进行修改。
  8. 缓存穿透、缓存雪崩、缓存击穿造成的原因是什么?怎么解决?
    答:

    • 缓存穿透:客户大量的访问缓存中不存在的键值,从而导致应用大量的去数据库中进行查询导致数据库压力过大。
      1. 对于用户访问不存在的键值将访问数据的数据也保存到缓存中,设置缓存失效的时间比较短即可;
      2. 使用布隆过滤器,过滤用户请求的键值数据
    • 缓存雪崩:缓存中的数据在某一刻大量的失效,从而导致此刻大量用户请求到达时,导致都去查询数据库,从而导致数据库的压力较大,设置有可能应用崩溃。
      1. 在设置缓存的键值失效时间时,对设置的时间再加上一个随机的时间,从而使键值不会在某一刻全部失效
      2. 对于热点数据,不设置失效时间,即永久存在
      3. 若是缓存数据库是分布式部署,将热点数据均匀的分布在不同的缓存数据库中
    • 缓存击穿:缓存数据库的某一条数据失效,而客户在此刻有大量请求进入,从而导致请求都去查询数据库,导致数据库压力较大。
      1. 设置互斥锁
      2. 设置热点数据不过期
  9. redis怎么实现高可用?
    答: redis实现高可用,可以采用集群部署以及哨兵模式。
    redis自身提供了集群部署的功能,采用redis-strib来实现集群部署。redis集群部署采用的一致性hash的数据结构,将redis需要保存数据的分为16384个槽,然后将些槽分布到集群中的redis节点,如果一个数据需要保存到redis时,即可通过获取键的hash值,算出键应该保存在哪个槽,从而计算保存在redis的哪个节点上。这样有个不好的地方是,如果需要后期扩展的时候,我们遵循一致性hash算法的特点,将顺时针临近的一个节点需要重新计算键的保存节点。所以最好在前期设计的时候就将redis的节点数量设置好。

  10. redis哨兵模式主要解决什么问题以及实现的原理?
    答:哨兵模式主要有两个功能,其一是监控各个redis节点是否正常工作;其二是当哨兵认为redis数据库处于客观下线的时候会将从数据库升级为主数据库。
    实现原理:

    • 哨兵节点会每隔10秒钟向主数据库发送info命令, 用于获取主数据库上从数据库的信息并且建立相关连接,并且监控主从数据库的列表信息。
    • 哨兵节点会每隔2秒钟向其主从数据库的sential:hello频道发送自己的哨兵节点信息,用于向其他哨兵节点通知自己的信息。
    • 哨兵节点会每隔1s表向主数据库发送ping命令,查看redis数据库是否还正常工作。
  11. redis复制的实现原理?
    答:

    • 当时用slaveof命令关联主数据库时,会建立一条连接,然后向主数据库sync/psync命令(如果redis是2.8版本之前,则发送的是sync命令,之后版本发送的是psync命令。)
    • 主数据库会在后台启动rdb保存,在保存期间会将客户新增的命令保存到缓存池,等到rdb传输完成之后,会将缓冲池中的命令传输给redis从数据库。
    • 主数据库发生更新时,会将命令放入到积压队列中,并记录传输给从数据库的偏移量。如果从数据库在半路重新同步时,只需要传入自身的主数据库Id和偏移量,主数据库会判断自身是否是这个id,然后判断偏移量是否还在,如果还在就将偏移量之后的数据传给从数据库,否则全量同步。
  12. redis对于内部不足时都有哪些策略淘汰键?
    答:

    • volatile-random: 设置了过期时间的键中随机淘汰
    • allkeys-random: 所有的键随机淘汰
    • volatile-lru: 设置了过期时间的键中最近最少使用原则
    • allkeys-lru: 所有键中使用最近最少使用原则
    • volatile-ttl 设置过期时间即将过期的键淘汰
    • noeviction: 不淘汰键,只返回错误
  13. redis对于键过期的执行策略有哪些?
    答:

    • 定时删除:在创建某个键时,同时执行这个键的过期删除定时器,当键过期时,定时器会删除该键,这种策略使用起来比较麻烦,redis未使用到。
    • 惰性删除:当客户端再次访问该键时,如果该键已过期,redis则会删除该键。
    • 定期删除:每隔一段时间,redis会检查内部的键是否过期,然后删掉过期的键。
  14. MyBatis中$和#符号的区别

  15. Java虚拟机在什么情况下会触发Full GC(老年代GC)?

    • 虚拟机启动了explicitGC的情况下,在代码中使用了System.gc的情况下,会触发Full GC。
    • 大对象直接进入老年代,但老年代不能的内存不能满足大对象的内存,从而会触发Full GC。
    • 分配担保机制失败的情况下,会触发一次Full GC。
    • Full GC一般情况下都会伴随着一次Monitor GC。
  16. Java生产问题排查步骤?
    答:针对不同的情况查问题也不同

    • 首先如果是界面报了Exception的相关错误,则可以查看Tomcat日志或者自定义的生产日志来查看报错具体的类和方法,定位问题是什么导致。
    • 如果是报出Error相关的异常,也可以通过查看日志来查找问题,查看是否是内存溢出还是内存泄露或者其他问题。
    • 如果界面发生响应速度慢、卡死、无响应、没有详细日志的情况,可以通过Top、vmstat、jps、jstat、jmap、jstack等命令来查看虚拟机的详细情况,分析是否发生了死锁或者频繁GC造成的相应变慢/卡死情况。
    • 如果发生系统崩溃,可以通过添加启动参数-XX:errorFile=”XXX” -XX:heapDumpOnOutofMemory的启动参数,查看是否有出错日志来定位问题在哪里。
  17. Java中ArrayList、LinkedList、Vector的区别?

  18. Spring中BeanFactory和ApplicationContext的区别?
    答:BeanFactory和ApplicationContext都是Spring容器。BeanFactory是Spring最底层的接口,只提供了getBean的相关方法。ApplicationContext继承BeanFactory,但提供了更多的功能。

    • ApplicationContext针对实现了BeanPostProcessor和BeanFactoryPostProcess的bean,只需要在XML中配置或者在类上声明即可,不需要手动添加。
    • ApplicationContext提供了资源访问的方法。
    • ApplicationContext支持事件机制,可以监听相关事件
    • ApplicationContext提供了国际化支持,
    • ApplicationContext在不需要重启服务的情况下可以刷新容器内部的Bean实例
    • ApplicationContext采用的是饿加载机制,即启动的时候加载实例化Bean,BeanFactory采用的是获取Bean信息时实例化。
  19. Spring中IOC你是怎么理解的?
    答:在未使用Spring IOC开发时,对象的实例化一般由开发人员自己实例化和管理,使用new关键字来实例化。而Spring IOC是将对象的实例化和周期管理交给了BeanFactory去处理,开发人员不需要管理对象的创建和销毁,只需要关注自己的业务处理即可。

  20. Spring中的事务传播机制有哪些?
    答:

    • PROPAGATION.REQUIRED: 默认的事务传播行为,如果当前有事务就加入到事务中,如果当前无事务则创建一个事务。
    • PROPAGATION.SUPPORTS:支持当前的事务,如果没有事务,则使用非事务的方式执行
    • PROPAGATION.MANDATORY:支持当前的事务,如果没有事务则抛出异常。
    • PROPAGATION.REQUIES_NEW:如果当前有事务,则挂起当前的事务创建一个新的事务执行业务
    • PROPAGATION.NOT_SUPPORTED: 不支持当前事务,如果存在当前事务,则将当前事务挂起,执行完毕之后在执行上下文事务
    • PROPAGATION.NEVER:不支持当前事务,如果存在当前事务则抛出异常
    • PROPAGATION.NESTED:支持事务嵌套,即新创建一个新的事务添加到原来的事务中。
  21. Spring的事务隔离级别有哪些?
    答:

    • DEFAULT: Spring默认的事务隔离级别,采用数据库自身的事务隔离级别机制。
    • READ_UNCOMMITED:未提交读。事务未提交时,其它事务可能会读取到当前的处理结果。会造成脏读、不可重复度、幻读。
    • READ_COMMITED: 提交读。事务提交之后,其它事务可以访问到当前的结果,会造成不可重复度、幻读。
    • REPEATABLE_READ:可重复读。一个事务可以重复查询而不会出现两次查询结果不一致的问题。避免不了幻读问题。
    • SERIALIZABLE: 串行化。读取和修改操作都会上锁,并发性差。
  22. Spring AOP理解?
    答:

    • 一般在开发中使用的都是OOP,面向对象开发,而AOP的意思是面向切面开发,这在一方面弥补了OOP开发的缺点。
    • 切点:描述哪些类、哪些方法。
    • 连接点:描述程序代码中一些比较有特定意义的点,比如是类初始化、方法执行前、方法执行后。
    • 增强:需要增加的功能代码。
    • 切面:由切点和曾庆组成的组合。
    • 织入:将增强功能添加到切面的过程。
    • 代理:目标对象添加之后返回的对象就是代理。
  23. Spring AOP都有哪些增强?

    • 前置增强:指在方法执行前,通过实现BeforeAdvice接口
    • 后置增强:指在方法执行完成后,通过实现AfterReturningAdvice接口
    • 环绕增强:指在方法执行前和执行后分别添加增强,通过实现MethodInceptor接口
    • 异常增强:指在方法抛出异常的情况下执行,通过实现ThrowsAdvice接口实现。
    • 引介增强:通过给指定的类添加属性或方法来扩展原来的方法。
  24. Spring AOP都有哪几种实现,区别是什么?
    答:

    • JDK动态代理:JDK动态代理目标对象必须实现接口,
    • CGLIB动态代理:CGLIB动态代理是采用生成子类的方式生成的代理对象的,因此不需要实现接口。CGLIB不能对目标对象中是final方法、private方法修饰生成代理。CGLIB的执行性能相对JDK动态代理较高,但创建代理的效率比较差。
  25. Spring AOP的实现原理是什么?
    答:

    • Spring AOP在启动的时候会向IOC注册一个Bean实例的后置处理器,该后置处理器会在BeanFactory第一次调用getBean方法或是使用ApplicationContext初始化时,利用该后置处理器创建出一个目标对象的代理类返回。
    • Spring在使用xml配置时,会将XML中的配置的增强注册到BeanRegistry中,在实例出Bean的时候进入到后置处理器,Spring AOP会发现那些适合目标对象的Advisor,将其添加到invoke方法中,从而生成增强。
  26. Spring Boot都有哪些特性?
    答:

    • 简化配置,Spring Boot内部使用了大量的自动配置,减少了开发人员进行不必要的配置。
    • 简化部署,Spring Boot内嵌了Tomcat、Jetty等web容器,开发人员不需要再部署一个Tomcat环境才能运行Web应用程序
    • 简化监控,Spring Boot内嵌了Actuator等依赖,可以直接使用rest方式查看应用的健康情况。
    • 简化编码,Spring Boot提供了大量的starter依赖包,开发人员不需要担心依赖包之间的冲突和查找需要的依赖包所花费的时间。
  27. Spring Boot是怎么实现自动配置的?

    • 在SpringApplication注解中有一个非常重要的注解@EnableAutoConfiguration,@EnableAutoConfiguration注解中有个@Import(AutoConfigurationImportSelector)注解,该注解在ConfigurationClassPostProcess工厂后置处理器中使用会解析Spring.factories中的EnableAutoConiguation实现类将其添加到Bean工厂中,从而实现自动配置。

集合详解-HashMap

发表于 2019-04-27 | 分类于 技术

我们为什么需要剖析HashMap集合类?

  • HashMap和HashTable有什么区别?
  • HashMap中默认的初始化容量和加载因子是多少?如果加载因子设置的太小会出现什么问题?如果设置的太大或出现什么问题?
  • HashMap中保存的元素是否可以包含null?保存的元素是否有序?
  • HashMap是否是线程安全的?如果多线程操作HashMap会出现什么问题?
阅读全文 »

并发编程总结

发表于 2019-04-26 | 分类于 技术

并发编程

优势

1.多处理器,充分利用系统资源
2.建模的简单性
3.异步处理,能够灵敏响应

问题

1.竟态性条件:多处理器操作在某个时间段,操作同一个地址,造成数据结果不正确
2.活跃性问题:多线程同步快之间发生相互调用,造成死锁,从而导致后续代码不执行,系统崩溃
3.性能问题:如果线程数量过大,并且线程切换比较频繁,则会造成CPU的使用消耗在上线文切换等操作,造成性能问题
##安全性问题解决
1.保证一个对象是无状态的:即保证一个类中的类变量和实例变量是无状态的。
2.操作是原子操作:对于基本的类型的,JAVA提供了原子变量类来实现基本类型的原子操作,其余的复合操作可以使用锁或者同步块,保证原子操作。
3.锁:锁是保证原子操作的一个重要的实现机制。

  • Lock接口
    • void lock():获取锁,调用该方法当前线程会获取锁
    • void lockInterruptibly(): 可中断的获取锁,在锁的获取中可以中断当前线程
    • boolean tryLock(): 尝试非阻塞的获取锁,调用该方法后立刻返回,如果能获取到则返回true,否则返回false
    • boolean tryLock(long time, TimeUnit unit):查实的获取锁
    • void unlock(): 释放锁
    • Condition newCondition():获取等待通知的组件,该组件和当前的锁绑定,当前线程获取锁然后调用组件的wait()方法,调用后释放锁。
      注意:Lock的主要实现依赖于AbstractQueueSynchronizer,一般在Lock的内部创建静态的队列同步器类
  • 队列同步器
    • getState(): 获取当同步器的状态
    • setState(): 设置当前同步器的状态
    • compareAndSetState(): 对比同步器的状态并设置新的状态,这个是原子操作
  • 重入锁
    • 同步块和ReenTryLock都隐式的使用了重入锁,即当前拥有锁的线程和想要获取锁的线程是同一个线程,则同步器的状态想要的增加,释放时也要多次释放。
  • 读写锁
    • 概述: 读写锁满足同一时刻允许多个线程进行读取,但是在写线程访问时,所有的读线程和写线程均阻塞。
    • 特性:
      a. 公平性选择
      b. 支持重进入
      c. 支持锁降级
    • ReentrantReadWriteLock的接口和示例:
      a. readLock: 获取读锁
      b. wirteLock: 获取写锁
      c. int getReadLockCount(): 返回当前读锁被获取的次数
      d. int getReadHoldCount(): 返回当前线程获取读锁的次数
      e. boolean isWriteLocked(): 判断写锁是否被获取
      f. int getWrieteHoldCount():返回当前写锁被获取的次数。
    • 读写锁的实现:也采用的是队列同步器的实现,需要通过个整型变量来维护多个读线程和一个写线程的状态,采用的是高16位代表读,低16位代表写。
  • LockSupport工具:
    • 概述:LockSupport工具提供了基本的线程阻塞和线程唤醒功能。
      a. void park(): 阻塞当前线程,直到调用unPark(Thread thread)方法或者当前线程被中断才返回。
      b. void parkNanos(long nanos): 阻塞当前线程最长不超过nanos纳秒。
      c. void parkUntil(long deadline): 阻塞当前线程
      d. void unPark(Thread thread): 唤醒处于阻塞状态的线程。
  • Condition接口
    • 概述:Condition接口也提供了类似Object的监视器方法,与Lock配合可以实现等待/通知模式(Condition condition =Lock.newCondition();
      注意:Condition接口具有多个队列,并且可以进入等待队列的线程可以不响应中断。
      a. void await(): 当前线程进入等待状态直到被中断或被通知。
      b.void awaitUninterruptibly(): 当前线程进入等待状态直到被通知。
      c. long awaitNanos(long nanos): 当前线程进入等待状态直到被通知、中断和超时。
      d. boolean awaitUtil(Date dealine): 当前线程进入等待状态直到被中断、通知和直到某个时间。
      e. void singal(): 唤醒condition队列等待的状态。
      f. void singalAll(): 唤醒Condition队列上所有等待的状态。
12>
Marchen

Marchen

原来我很快乐,只是不愿承认

15 日志
2 分类
24 标签
0%
© 2020 Marchen
由 Hexo 强力驱动
|
主题 — NexT.Gemini v5.1.4