多线程
# 多线程
# 使用多线程的原因
并发编程的目的就是为了能提高程序的执行效率提高程序运行速度,但是并发编程并不总是能提高程序运行速度的。
从计算机底层来说:线程是程序执行的最小单位,线程间的切换成本低。多核CPU意味着多线程可以同时运行,减少了线程上下文切换的开销。
从互联网发展趋势来说:现在系统动不动就要求百万七万级的并发量,多线程并发编程正式开发高并发系统的基础,利用多线程机制可以大大提高系统整体的并发能力和性能。
单核时代多线程的意义?
在单核时代多线程主要是为了提高进程利用CPU和IO系统的效率。假设只运行一个Java进程的情况,当我们请求IO的时候,如果Java进程只有一个线程,此线程被IO阻塞则整个进程就被阻塞了。CPU和IO设备只有一个在运行,那么系统效率大大降低。当使用多线程的时候,一个线程被IO阻塞,其他线程还可以继续使用CPU,从而提高了Java进程利用系统资源的整体效率。
多核时代多线程的意义?
多核时代多线程主要是为了提高进程利用多核CPU的能力。计算一个复杂的任务,我们只用一个线程的话,无论系统有几个CPU核心,都只有一个CPU核心被利用。当创建多个线程时,这些线程可以在多个CPU上执行,效率会显著提高。
# 多线程的优缺点
优点:
- 充分利用CPU,避免CPU空转
- 程序相应更快。
缺点:
上下文切换的开销大
当CPU从执行一个线程到切换到执行另外一个线程时,他需要先存储当前线程的本地数据,程序指针,然后加载另外一个线程的本地数据,程序指针,最后才开始执行。这种切换称为上下文切换。CPU会在一个上下文中执行一个线程,然后切换到另一个上下文中执行另外一个线程,上下文切换费时,如果没必要尽量减少上下文切换的发生。
增加资源消耗
线程在运行时需要从计算机里面得到一些资源。除了CPU,线程还需要一些内存来维持它的虚拟机栈栈。
编程更加复杂,需要考虑多线程安全的问题。
容易造成内存泄漏、死锁等问题
# Runnable和Callable的区别
- Callable定义的方法是call(),而Runnable定义的方法是run()
- Callable的call方法可以有返回值,而Runnable的run方法不能有返回值。
- Callable的call方法可以抛出异常,而Runnable的run方法不能抛出异常。
# sleep()和wait()的区别
- sleep()属于Thread类,wait()方法属于Object类。
- 两者都可以暂停线程的执行。
- 最主要区别:sleep没有释放锁,wait释放锁。
- wait通常被用于线程间交互,sleep通常被用于暂停执行。
- 使用wait、notify、notifyAll只能在同步方法或同步代码块中使用。
- wait被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的notfiy和notifyAll方法,或者使用wait(long timeout)超时后线程会自动苏醒。sleep方法执行后,线程会自动继续运行。