1. 进程和线程的基本概念
进程是系统分配资源的基本单位. 进程是操作系统对正在运行程序的一种抽象,可以将进程看作程序的一次运行。
线程是系统调度执行的基本单位. 一个线程是一个"执行流". 线程自己不拥有系统资源, 它与同一进程的其它线程共享同一份系统资源, 同一进程中的多个线程可以并发执行.
线程的特点
- 线程是轻量级进程.
- 同一个进程中的多个线程共享同一份系统资源. (创建线程就省去了申请资源的开销, 销毁线程也省去了释放资源的开销)
- 每个线程, 都是一个独立的执行流, 可以独自参与到 cpu 的调度.
- 当有多个线程的时候, 这些线程的执行顺序是不确定的, 因为操作系统中, 有一个 "调度器" 模块, 这个模块的调度方式, 是类似于 "随机调度" 的.
2. 进程与线程之间的区别(重点)
- 一个进程包含多个线程.
- 每个线程, 是一个独立的执行流, 可以执行一些代码, 并且单独参与到 cpu 的调度中
- 每个进程有自己的资源, 进程中的线程共享同一份资源 (内存 + 文件描述符表)
- 进程和进程之间, 不会相互影响, 如果同一进程中的某个线程抛出异常, 可能会影响其他线程, 会把整个进程中的所有线程都异常终止.
- 线程上下文切换比进程上下文切换要快得多。
- 同一进程中的线程之间, 可能会相互干扰, 引起线程安全问题.
- 线程也不是越多越好, 要能够合适, 如果线程过多, 调度开销可能会非常明显.
3. 创建线程
run方法是线程的入口.
调用start() 之后, 才是启动线程, 这时此线程处于就绪(可运行)状态.
class MyThread1 extends Thread{
@Override
public void run() {
while(true){
System.out.println("hello Thread");
}
}
}
public class ThreadDemo1 {
public static void main(String[] args) {
MyThread1 t = new MyThread1();
t.start();
while(true){
System.out.println("hello main");
}
}
}
代码执行以后, 就是不断循环打印hello main和 hello Thread.
如果是单线程, 就只能执行一个死循环, 而现在, 两个循环都能执行, 这就是并发.
lambda 表达式
创建线程的方法, 最常用也是最推荐的方法就是 lambda 表达式.
public class ThreadDemo5 {
public static void main(String[] args) {
Thread t = new Thread(()->{
while(true){
System.out.println("hello thread");
try {
sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t.start();//调用start才会创建线程
}
}
我们代码创建的线程, 默认是前台线程, 会阻止进程结束, 只要前台进程不结束, 进程就不会结束, 即使 main 线程已经执行完毕.
使用setDaemon(), 设为true 是后台, 不设为true 是前台.
public class ThreadDemo4 {
public static void main(String[] args) {
Thread t = new Thread(new Runnable(){
@Override
public void run() {
while(true){
System.out.println("hello thread");
try {
sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
},"这是我的线程");
//代码创建的线程默认是前台线程, 阻止进程结束
//在start之前设置成后台线程,不能在start之后设置
t.setDaemon(true);
t.start();
}
}
isAlive()
表示了, 内核中的线程(PCB) 是否还存在.
Java 代码中定义的线程对象实例, 虽然表示一个线程, 但这个对象的生命周期, 和内核中的PCB生命周期是完全不一样的.
此时 t 对象有了, 但内核PCB还没有, 此时 isAlive 就是false.
t.start() 才在内核中真正创建出PCB, 此时isAlive 就是true.
当线程 run 执行完了, 此时内核中的线程也就结束了, 内核中的PCB也就释放了,
但此时 t 变量可能还存在, 但 isAlive 也是false.
好啦, 我们下个文章见~~