28多线程与并发原理

为什么需要多线程

  • CPU :你们都慢!死!了!

    • 一个现代的3Ghz的cpu做一件事情是0.3纳秒
    • 比如一个a+1,cpu先从内存取出来一个a,然后在cpu中进行一个+1操作再放回去,一来一回有多慢呢,内存的寻址时间一般是10微秒
    • cpu明明这么快,奈何小伙伴不给力,以至于cpu频繁的停下来等小伙伴,可以在等小伙伴的时候做其他的事情
  • 现代CPU都是多核的

    • 现在的CPU一般是3Ghz=3G时钟周期/s,2000年那时候的CPU频率大概是233Mhz,CPU做事的时钟周期一般是恒定的,同样做3时钟周期的事,3Ghz比233Mhz所需的时间下降了一千倍,CPU的频率从2008年就再也没上升过了,既然越快越好,为什么不能做到10Ghz、100Ghz,焦耳定律,CPU频率越快发热量越大,发热量严重制约了CPU频率的上升,但是我们又想要更快的电脑,解决方案就只有一个了:堆核心
    • 现代CPU理论上天然具有并发能力
  • 提高cpu利用率

  • Java的执行模型是同步/阻塞(block)的

    如果在进行一个非常耗时操作,线程的执行流或者说方法的执行流会停在这里,等着这个方法执行完,这个过程叫阻塞

    public class Crawler {
      public static void main(String[] args) throws InterruptedException {
          a();
          System.out.println(1);
      }
    
      private static void a() throws InterruptedException {
          Thread.sleep(10000);
          b();
      }
    
      private static void b() throws InterruptedException {
          Thread.sleep(10000);
      }
    }
  • 默认的情况下只有一个线程

    • 处理问题非常自然
    • 但是具有严重的性能问题

开启一个新的线程

Thread

  • Java中只有这么一种东西代表线程
  • start方法才能并发执行!
  • 每多开一个线程,就多一个方法栈(执行流),Thread().start的入口就是run
  • 方法栈是线程私有的
    • 局部变量是方法栈私有的,只能被当前线程被访问、被看到(为了保证线程中的局部变量不被别的线程访问到) ,方法栈的所有栈帧都是线程私有的
  • 静态变量/类变量是被所有线程共享的
  • run()与start()的区别
    start() 启动了一个新的线程,run()普通成员方法,不会启动新的线程

线程难的本质原因是

  • 你要看着同一份代码,想象不同的人在疯狂地以乱序执行它(线程的随机性)

多线程带来的性能提升

  • 对于IO密集型应用极其有用
    • 网络IO(通常包括数据库)
    • 文件IO
  • 对于CPU密集型应用稍有折扣
  • 性能提升的上限在哪里?
    • 单核CPU 100%
    • 多核 CPU N*100%
点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注