多线程概念
1 线程
是进程中的一个执行单元,负责当前进程中任务的执行。一个进程在其执行过程中,会产生很多个线程。
2 进程
是指内存中运行的一个应用程序,每个进程都有自己独立的内存空间;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。
区别
进程:有独立内存空间,每个进程中的数据空间都是独立的。
线程:多线程之间堆空间与方法区是共享的,但每个线程的栈空间、程序计数器是独立的,线程消耗的资源比进程小的多。
3 并发
同一时间段,多个任务都在执行 ,单位时间内不⼀定同时执行。
4 并行
单位时间内,多个任务同时执行,单位时间内一定是同时执行。并行上限取决于CPU核数(CPU时间片内50ms)
并行是受到物理机器限制的,但是并发是可以通过系统设计来提高
上下文切换
因为CPU都是一般都是多核,所以操作系统采用了时间分片算法进行调度。当线程拿到时间片就执行,当时间片消耗完了,就会被挂起,把资源让给其它线程。
CPU会将当前的任务状态保存下来,用于下次切换回任务时再加载。保存任务状态及再加载的过程就叫上下文切换
。
上下文切换过程:
- 挂起当前任务任务,将这个任务在 CPU 中的状态(上下文)存储于内存中的某处。
- 恢复一个任务,在内存中检索下一个任务的上下文并将在 CPU 的寄存器中恢复。
- 跳转到程序计数器所指定的位置(即跳转到任务被中断时的代码行)。
这个过程存在一些问题,也就是说如果线程特别多,这个时候资源竞争激烈,这个时候上下文切换消耗的资源可能比任务执行还要多,所以实际开发中将线程的数量设置到一个合理的值,这样才能够提高应用 的运行效率。
由于上下文切换的时候线程会被挂起,这个时候如果是高并发就可能产生一些问题,所以在高并发编程的时候需要考虑这种情况,可能是极端并发中的一种情况。
线程的生命周期(非常重要)
1 线程的状态
public enum State {/*** Thread state for a thread which has not yet started.*/NEW,/*** Thread state for a runnable thread. A thread in the runnable* state is executing in the Java virtual machine but it may* be waiting for other resources from the operating system* such as processor.*/RUNNABLE,/*** Thread state for a thread blocked waiting for a monitor lock.* A thread in the blocked state is waiting for a monitor lock* to enter a synchronized block/method or* reenter a synchronized block/method after calling* {@link Object#wait() Object.wait}.*/BLOCKED,/*** Thread state for a waiting thread.* A thread is in the waiting state due to calling one of the* following methods:* <ul>* <li>{@link Object#wait() Object.wait} with no timeout</li>* <li>{@link #join() Thread.join} with no timeout</li>* <li>{@link LockSupport#park() LockSupport.park}</li>* </ul>** <p>A thread in the waiting state is waiting for another thread to* perform a particular action.** For example, a thread that has called <tt>Object.wait()</tt>* on an object is waiting for another thread to call* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on* that object. A thread that has called <tt>Thread.join()</tt>* is waiting for a specified thread to terminate.*/WAITING,/*** Thread state for a waiting thread with a specified waiting time.* A thread is in the timed waiting state due to calling one of* the following methods with a specified positive waiting time:* <ul>* <li>{@link #sleep Thread.sleep}</li>* <li>{@link Object#wait(long) Object.wait} with timeout</li>* <li>{@link #join(long) Thread.join} with timeout</li>* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>* </ul>*/TIMED_WAITING,/*** Thread state for a terminated thread.* The thread has completed execution.*/TERMINATED;}
- NEW(新建) :线程刚被创建,但是并未启动
- RUNNABLE(可运行):线程可以在Java虚拟机中运行的状态,可能正在运行自己代码,也可能没有,这取决于操作系统处理器
- BLOCKED(锁阻塞):当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态
- WAITING(无限等待):一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒
- TIMED_WAITING(计时等待):同waiting状态,有几个方法有超时参数,调用他们将进入TimedWaiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep 、Object.wait
- TERMINATED(被终止):因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。
状态之间的转换关系,非常重要
wait()与sleep()区别:
- 主要区别:sleep()方法没有释放锁,而wait()方法释放了锁
- 两者都可以暂停线程的执行
- wait()通常用于线程间的交互/通信,sleep()通常用于暂停线程执行
- wait()方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象的notify或notifyAll。
- sleep()方法执行完成后,线程会自动苏醒。或者可以使用wait(long)超时后,线程也会自动苏醒