一、并行与并发
并发:任务交替执行,看起像在同时进行。
并行:任务同时进行。
二、线程与进程
进程是操作系统分配资源的最小单位,进程与进程之间是相互独立的;
线程是CPU调度的最小单位,一个进程可以有多个线程;
同进程的线程可以共享进程的大部分资源,线程自身也拥有一点自己的资源,比如程序计数器、栈等。
三、CPU与线程
CPU核数与线程数:理论上是1:1的关系比较好;但是超核技术让CPU可以与线程达到1:2的关系。
CPU时间片轮转机制:CPU调度线程,是交替执行,也就是说是并发的。CPU将调度时间分片,每个线程轮流获得时间片,这让线程看起来是并行的,实际是并发执行。
CPU时间片轮转机制比较关键的问题是时间分片的长度,时间片太长会导致有些线程有明显卡顿感;时间片太短会大大浪费CPU切换所需要的时间。一般为200ms比较合适。
四、线程的方法
start():让线程处于就绪状态,等待CPU时间片,执行start()方法,run()才是真正在线程中.
run():一般不能主动调用,只能重写,实现业务逻辑。
suspend():暂停,过期方法,不建议使用,因为暂停不会释放锁等操作,容易导致死锁,不安全;
resume():继续,和suspend()一样,不建议使用
stop():停止,过期方法,不建议使用,不释放锁,容易导致死锁,不安全。
interrupt():设置中断标记,实际是否中断由代码逻辑检测中断标记控制;
isInterrupted():判断是否被中断
Thread.interrupted():判断是否被中断,并且将中断标记置为false
yield(): 让出CPU资源,但不释放锁,所以执行完之后可能继续夺取CPU资源
join(): B线程中,调用A线程的join(),B线程将挂起,直到A线程执行完才执行B线程
setPriority(int):设置线程优先级,0-10,一般为5,越大则分配的时机片越多,但不一定。
setDaemon(true):设置为守护线程,主线程退出以后,守护线程自动退出,比如垃圾回收线程
注意:wait()、notify()是Object类的方法。
yield() 、sleep()被调用后,都不会释放当前线程所持有的锁。调用wait()方法后,会释放当前线程持有的锁,而且当前被唤醒后,会重新去竞争锁,锁竞争到后才会执行wait 方法后面的代码。调用notify()系列方法后,对锁无影响,线程只有在syn 同步代码执行完后才会自然而然的释放锁,所以notify()系列方法一般都是syn 同步代码的最后一行。wait()和notify()务必在synchronized代码块中使用。
wait()、notify()配合使用,可以实现线程间协作。
线程A在synchronized代码块中执行对象O的wait(),释放锁,进入等待,线程B获得锁,执行逻辑,通过对象O的notify()通知线程A执行wait()之后的代码。
五、线程的状态
Java中线程的状态分为6种:
- 初始:新创建了一个线程对象,但还没有调用start()方法。
- 运行:Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。 - 阻塞:表示线程阻塞于锁。
- 等待:进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
- 超时等待:该状态不同于WAITING,它可以在指定的时间后自行返回。
- 终止:表示该线程已经执行完毕。
网友评论