1.进程和线程的区别
程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至 CPU中,数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的。
当一个程序被运行,从磁盘加载这个程序的代码到内存中,这时就开启了一个进程。什么叫做进程:当一个程序被允许,从磁盘加载到这个程序的代码至内存,这时就开启了一个进程。(比如:打开QQ软件,QQ运行后就是一个进程)
什么叫做线程:线程就是一个指令流,将指令流中的一条条指令以一定顺序交给CPU执行。
进程和线程的区别:
- 进程是正在运行程序的实例,进程中包含了多个线程,每个线程执行不同的任务。
- 不同的进程使用不同的内存空间(QQ进程与微信进程使用的内存空间是不同的),当前进程下的所有线程可以共享内存空间。
- 线程比进程更轻量,线程上下文切换成本一般比进程低(上下文切换指的是一个线程切换到另一个线程)
2.并行和并发的区别
两种情况:单核CPU和多核CPU
1.单核CPU
- 单核CPU下线程实际还是串行执行的
- 操作系统中有一个组件叫做任务调度器,将cpu的时间片(windows下时间片最小约为 15 毫秒)分给不同的程序使用,只是由于cpu在线程间(时间片很短)切换的速度非常快,给人的感觉是同时运行的 。
- 总结为一句话就是: 微观串行,宏观并行
- 一般会将这种线程轮流使用CPU的做法称为并发(concurrent)
2.多核CPU
每个核(core)都可以调度运行线程,这时候线程可以是并行的。
3.并行和并发有什么区别?
并发(concurrent)是同一时间应对(dealing with)多件事情的能力,(在同一刻时间上,还是只做一件事)
并行(parallel)是同一时间动手做 (doing)多件事情的能力,(同一刻时间内,多核CPU同时做多件事)
4.总结
现在都是多核CPU,在多核CPU下
并发是同一时间应对多件事情的能力,多个线程轮流使用一个或多个CPU
并行是同一时间动手做多件事情的能力,4核CPU同时执行4个线程
3.创建线程的方式有哪些?
- 继承Thread类
- 实现Runnable接口
- 实现Callable接口
- 线程池创建线程(项目中常用的方式)
1.runnable与callable有什么区别?
- runnable没有返回值,callable的返回值类型与泛型一样。
- runnable不能向上抛出异常,只能内部消化,callable可以抛出异常。
- callable可以用Future、FutureTask获取线程的返回值。
2.线程的run和start有什么区别?
- run相当于一个普通方法,可以在一个线程中多次执行,而start是开启一个线程,一个线程只能开启一次,多次调用就会抛出异常。
- run(): 封装了要被线程执行的代码,可以被调用多次。
- start(): 用来启动线程,通过该线程调用run方法执行run方法中所定义的逻辑代码。start方法只能被调用一次。
4.线程包括哪些状态,状态之间如何变换?
线程的状态可以参考JDK中Thread类中的枚举State。
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 {@code Object.wait()} * on an object is waiting for another thread to call * {@code Object.notify()} or {@code Object.notifyAll()} on * that object. A thread that has called {@code Thread.join()} * 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; }
简化:
1.线程的6种状态
- 新建(new)。
- 可执行(runnable)。
- 阻塞(blocked)。
- 等待(waiting)。
- 时间等待(timed_waiting)。
- 终止(terminated)。
2.线程状态之间的变化
1.创建线程对象是新建状态。
2.调用start()方法转变为可执行状态。
3.线程获取到了CPU的执行权,执行结束是终止状态。
4.在可执行状态的过程中,如果没有获取到CPU的执行权,可能会切换其它的状态。
(*).如果没有获取到锁(synchronized或lock)进入阻塞状态,获得锁再切换为可执行状态。
(*).如果线程调用了wait()方法进入等待状态,其它线程调用notify()唤醒后可切换为可执行状态。
(*).如果线程调用了sleep()方法,进入计时等待状态,到时间后可切换为可执行状态。
* 表示没有先后顺序
5.新建T1、T2、T3三个线程,如何保证它们按顺序执行?
可以使用线程中的join方法解决。