进程和线程
进程
1)进程就可以视为程序的一个实例。大部分程序可以同时运行多个实例进程(例如记事本、画图、浏览器 等),也有的程序只能启动一个实例进程(例如网易云音乐、360 安全卫士等)。
2)系统进程:用于完成操作系统的各种功能的进程,它们就是处于运行状态下的操作系统本身
3)用户进程:就是所有由用户本身启动的进程
4)站在操作系统的角度,进程是程序运行资源分配(以内存为主)的最小单位
线程
1)有限的CPU运行多个程序:CPU调度多个进程中的线程
2)线程是CPU调度的最小单位
3)线程必须依赖于进程而存在,线程是进程中的一个实体,是能独立运行的基本单位
4)线程拥有在运行中必不可少的资源(如程序计数器,一组寄存器和栈)
5)线程可与同属一个进程的其他的线程共享进程所拥有的全部资源
6)一个进程可以拥有多个线程,一个线程必须有一个父进程
7)早期Linux的线程实现几乎就是复用的进程,后来才独立出自己的API。
上下文切换
CPU从一个进程或线程到另一个进程或线程的切换
上下文是CPU寄存器和程序计数器在任何时间点的内容
一次上下文切换大概需要5000~20000个时钟周期,相对一个简单指令几个乃至十几个左右的执行时钟周期,成本巨大
过程
1)暂停一个进程的处理,将该进程的CPU状态(即上下文)存储在内存中的某个地方
2.)从内存中获取下一个进程的上下文,并在CPU的寄存器中恢复它
3.)回到程序计数器指示的位置(即返回到进程被中断的代码行)以恢复进程
寄存器
寄存器是CPU内部的一小部分非常快的内存(相对于CPU内部的缓存和CPU外部较慢的RAM主内存),通过提供对常用值的快速访问来加快计算机程序的执行
程序计数器
是一种专门的寄存器,指示CPU在其指令序列中的位置,并保存着正在执行的指令的地址或下一条要执行的指令的地址
并行和并发
并行
并行(parallel):指在同一时刻,有多条指令在多个处理器上同时执行。所以无论从微观还是从宏观来看,二者都是一起执行的。 并行在多处理器系统中存在
并发
并发(concurrency):指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个进程快速交替的执行。并发可以在单处理器和多处理器系统中都存在。
Java线程
内置线程
启动线程的方式
1)继承thread
public class MyThread extends Thread {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}/**
* 重写Thread类的run(),这个方法称为线程执行体
*/
@Override
public void run() {
doSomething();
}/**
* 需要处理的任务
*/
public void doSomething() {
}
}
2)实现runnable
public class MyRunnable implements Runnable {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();}
/**
* 实现Runnable接口的run方法,这个方法称为线程执行体
* */
@Override
public void run() {
doSomething();
}/**
* 需要处理的任务
* */
private void doSomething(){
}
}
3)实现Callable接口
public class MyCallable implements Callable<String> {
public static void main(String[] args) {
Callable<String> callable = new MyCallable();
FutureTask<String> task = new FutureTask<>(callable);
new Thread(task).start();
try {
System.out.println(task.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
@Override
public String call() throws Exception {
doSomething();return "返回值";
}public String doSomething() {
return “返回值”;
}
}
4)线程池
public class ThreadPool implements Runnable {
private String name;
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(2);
ThreadPool threadPoolA = new ThreadPool("A");
ThreadPool threadPoolB = new ThreadPool("B");
pool.execute(threadPoolA);
pool.execute(threadPoolB);
pool.shutdown();
}
public ThreadPool(String name) {
this.name = name;
}@Override
public void run() {
doSomething();
}/**
* 需要处理的任务
* */
private void doSomething() {
}
}
run()和start()
中止
1)自然终止 run 执行完成或者抛出了一个未处理的异常导致线程提前结束。
interrupt(): 将线程的中断标志位设置为true,不会停止线程
isInterrupted(): 判断当前线程的中断标志位是否为true,不会清除中断标志位
interrupted():判断当前线程的中断标志位是否为true,并清除中断标志位,重置为fasle
中断机制是一种协作机制,并不能直接终止另一个线程,而需要被中断的线程自己处理。
被中断的线程拥有完全的自主权,它既可以选择立即停止,也可以选择一段时间后停止,也可以选择压根不停止。
4)优雅停止线程
while (!Thread.currentThread().isInterrupted() && more work to do) {
......
}
sleep可以被中断 抛出中断异常:sleep interrupted, 清除中断标志位
wait可以被中断 抛出中断异常:InterruptedException, 清除中断标志位
线程的状态
流程图:
待补充..
线程间的通信
volatile
wait notify
LockSupport
管道输入输出流
join