为什么需要多线程
-
- 一个现代的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%