• 峰
    2019-07-27
    讲真,我是觉得设计模式是优化代码组织结构的,性能提升只是因为你的实现途径导致了你适合用某种设计模式,so感觉这样标题怪怪的。

    如果要这么说的话,mapreduce或者说javase引入的forkjoin,流水线模式,cow就都是了。

    作者回复: 是的,有些设计模式更多的是优化代码逻辑结构,但还是有很多设计模式也起到了优化性能效果。例如,文中的Worker-Thread 设计模式其实就是一种线程池的优化方式,在并发量大时,一般的代码逻辑要么是串行执行,要么使用创建线程并发执行,在大量并发时两者都可能会出现性能瓶颈,而这种Worker-Thread 这样的设计方式则即可以并发执行,又避免创建过多的线程导致性能瓶颈。

    
     7
  • Jxin
    2019-07-29
    1.最常用的多线程设计模式应该是生产者消费者模式,在分布式系统,该模式现在一般也由Mq来承接。(以rocketMq为例)好处有:消峰,解耦,消息堆积,多broker并行消费,单broker串行(顺序)消费,发布订阅,分组消费,失败重试,死信管理等等。
    2.其他的业务不常用,比如lmmutability(不变模式,Long类的内部静态类对象池),还有个实时赋值COW,指得一提的应该还有个Actor,但java不支持,要玩又得引第三方包,所以java生产也不会用。
    3.forkjoin并行处理也是使用的多线程执行子任务,但这个应该算不上多线程设计模式,感觉说是多线程应用更好,其中的任务窃取挺有意思。

    作者回复: 很赞

    
     5
  • 张德
    2019-07-30
    老师好 我还用过reactor模式 这个多线程的thread-per-message感觉和reactor模式有点像 又有一些区别 但我就是总结不出之间的区别 老师能不能点化一下 多谢

    作者回复: 我们在之前也讲过reactor模式,reactor模式是基于事件驱动,并且有专门有一个监听线程池监听事件,一旦有事件进来,将会再通过handler线程池来处理具体的业务,实现更为复杂,性能要比thread-per-message更佳

     1
     2
  • aoe
    2019-10-10
    除了文中第一个设计模式,其他设计模式在《图解Java多线程设计模式》中都有更详细的介绍。感谢老师的分享,如果能在专栏的第一篇文章中推荐一些相关的书籍就更好了。
    
     1
  • 风轻扬
    2019-09-14
    //InputStreamReader读取原始的字节流,FileReader继承自InputStreamReader
                    br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    out = new PrintWriter(socket.getOutputStream(), true);
                    while ((msg = br.readLine()) != null && msg.length() != 0) {
                        System.out.println("server received:" + msg);
                        out.write("received~\n");
                        out.flush();
                    }
    老师,您在新建PrintWriter实例的时候,已经设置了自动刷新。为什么还要out.flush呢?这一句是多余的吧?
    展开

    作者回复: 是的,多余了

    
     1
  • -W.LI-
    2019-07-28
    老师啊!有没有好的书推荐,我觉得设计模式很好,源码应该是学习设计模式最好的老师,可是我的能力看源码感觉太早了。我就之前看过header first。感觉理解完全不够。好的设计模式和算法都能在系统性能有瓶颈的时候提升系统。我认识到它的重要了可是不得门,入不了难受啊。

    作者回复: 我记得大学时候读过一本《大话设计模式》的书籍不错,讲解的通俗易懂。

     2
     1
  • QQ怪
    2019-07-27
    比起Worker-Thread 设计模式类似工厂车间工人的工作模式,还有用的比较多的是生产者和消费者模式,与之前的不同的是,生产者和消费者模式核心是一个任务队列,生产者生产任务到任务队列中,消费者从队列消费任务,优点是解耦和平衡两者之前的速度差异。

    作者回复: 对的,分析的很到位。下一讲中我们会详细聊到生产者消费者模式。

    
     1
  • nightmare
    2019-07-27
    一个注册逻辑,下面有注册实现数组,注册实现里面有队列,并且本身实现runable ,注册门面依次从注册实现数组获取一个注册实现 并把请求放到注册实现的队列中,请求由一个注册实现来完成,请求由唯一的注册实现来完成,不会有并发问题 而且如果 注册实现有复杂业务 还可以加上 work thread模式来优化

    作者回复: 赞,现学现用

    
     1
  • 停三秒
    2020-02-01
    老师,其实我觉得worker-thread设计模式就是生产者消费者模式。执行流水线的take的Worker就是消费者,执行put的一方就是生产者。
    
    
  • 龙疯疯
    2019-12-13
    还是不明白Worker-Thread 设计模式相比普通线程池的优点是什么呢,两者都可以创建固定的线程,都会在满载时等待。

    作者回复: 是的,原理都是生产者消费者模式。

    
    
  • 风轻扬
    2019-09-14
    老师,前几天看了一篇帖子,上面说System.currentMills在高并下下也会有性能问题。我看您直接用的,并没有做优化。您在实际工作中,有没有碰见过System.currentMills影响性能的例子呢?

    作者回复: 这个性能我猜是说的相对的,只是说System.currentTimeMillis() 性能损耗更大

    
    
  • godtrue
    2019-09-12
    我们的项目中有用上下文模式,为了记录业务中间的关键操作步骤,不过比较挫是传输参数的方式,下次可以改版为使用ThreadLocal形式的。
    看到有同学问异步的问题,我也有这样的疑问,我想异步调用为了更好的性能,但是我也想要调用后的结果。
    问题如下:
    1:这种异步是真异步嘛?
    2:这种异步最终还是必须阻塞等待获取响应结果的,性能提升有多大空间呢?看主线程继续处理某些事情的速度快,还是异步任务线程的执行速度快?如果异步执行的响应速度更快,那他需要等待主线程执行完再给他结果?还是会中断主线程将结果给他?
    3:最关键是异步的结果怎么拿到,这是什么原理?
    展开

    作者回复: 异步是有场景条件的,例如,异步调用用户不需要感知结果,或者用户的客户端与服务端是一个tcp长连接,处理之后由服务端推送处理结果给用户。

    
    
  • 晓杰
    2019-08-08
    请问老师,worker thread模式和线程池是不是一样的

    作者回复: 实现的基本原理是一样的

    
    
  • Liam
    2019-07-29
    老师好,文中提到,通过threadlocal动态切换数据源是什么意思?指的是用一个threadlocal的map管理多数据源的连接,每次都从map去拿不同datasource的连接吗?

    作者回复: 对的,例如读写分离,ThreadLocal存放了读从库数据源和写主库数据源,如果是查询操作,则切换为读数据源,如果是新增修改删除操作,则切换为写数据源。

    
    
  • -W.LI-
    2019-07-28
    老师好!Thread-Per-Message 设计模式就是分离阻塞和非阻塞的呗。阻塞的部分通过多路复用。非阻塞的的那部分就丢线程池并发处理。
    
    
  • 晓杰
    2019-07-28
    请问老师packageChannel中的成员变量count不会存在线程安全问题吗

    作者回复: 我们对put take方法已经加锁了,所以是线程安全的。

    
    
  • 陆离
    2019-07-27
    老师,讲到并发这里,我想问一个前面讲过的synchronized锁升级的几个问题。
    1.当锁由无锁状态升级到偏向锁时,除了将Mark Work中的线程ID替换是否还有其他操作?替换完线程ID就代表获取到了锁吗?
    2.当锁状态为偏向锁状态时, 其他线程竞争锁只是CAS替换线程ID吗?如果之前的线程还没有执行完呢?
    3.针对第2个问题,假设线程T1获取到了偏向锁,将线程ID设为T1。线程T2尝试获取偏向锁时,先检测锁的Mark Word线程ID是否为T2,如果不是,会CAS替换,这个时候的期望值为null,更新值为T2,失败后进入偏向锁撤销。stop-the-world后检测T1是否存活,如果否清空Mark work线程ID,锁恢复为无锁状态,唤醒T2,接着尝试获取锁。流程是这样的吗?
    4.当锁升级为轻量级锁时,获取锁的标志是锁指针指向线程的锁记录,当有其他线程尝试CAS获取锁时,期望值是无锁时,Mark word中为hash age 01这样的内容吗?
    5.当线程释放轻量锁时,需要将锁记录替换回Mark Word中,这种情况下锁还未释放为什么会有失败?
    6.当锁升级为重量锁后,开始使用monitor对象,为什么Mark Word中还会把内容替换为指向线程锁记录的指针?这个时候还需要使用Mark word吗?
    期待老师及同学的解答
    展开

    作者回复: 1、替换之后,“是否偏向锁”标志位设置为 1;
    2、如果获取锁失败,代表当前锁有一定的竞争,偏向锁将升级为轻量级锁;
    3、是的;
    4、标志位为00;
    5、如果是锁释放轻量级锁,直接将指向轻量级锁的指针置为null就可以了;
    6、这个是轻量级升级为重量级就会带过来的,暂时没有观察到具体的作用

     2
    
  • undifined
    2019-07-27
    老师,有一个问题没想明白,就是异步的请求处理中,每一个线程接收将请求交给处理的线程后,怎么拿到返回结果并返回给用户呢

    作者回复: 可以通过Future模式拿到返回结果,虽然是异步执行,如果要等待返回结果,则主线程还是在阻塞等待。

    
    
我们在线,来聊聊吧