线程基础知识,什么是程序、进程、线程、线程的生命周期、并行、并发、线程的创建

61 阅读4分钟

多线程

概念

  1. 程序(Program)

    语言编写的指令集合,指一段静态的代码。

  2. 进程

    动态的,一个正在运行的程序,及程序的一次执行过程,存在[生命周期]。可并发多个线程,每条线程执行不同任务

    进程的三种状态

    1. 就绪态
    2. 运行态
    3. 阻塞态
  3. 线程

    进程中的一个单一顺序的控制流,作为调度和执行的最小单位,每个线程都拥有独立的运行栈和程序计数器,切换的开销小,共享同一个进程中的结构(方法区、堆)

    线程的六种状态

    1. New(新建)
    2. Runnable(可运行)
    3. Blocked(阻塞)
    4. Waiting(等待)
    5. Timed Waiting(超时等待)
    6. Terminated(终止)
  4. 单线程

    单线程的也就是程序执行时,所跑的程序路径(处理的东西)是连续顺序下来的,必须前面的处理好,后面的才会执行到。

  5. 多线程

    多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务, 也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

  6. 并发

    把任务在不同的时间点交给处理器进行处理。在同一时间点,任务并不会同时运行

  7. 并行

    把每一个任务分配给每一个处理器独立完成。在同一时间点,任务一定是同时运行

线程实现的两种方式

  1. 继承Thread类 (实现了Runnable接口,重写run方法)
  2. 实现Runnable接口

线程执行流程图

1.继承Thread类

  • 当在main线程中启动一个子线程,main线程不会阻塞
  • 主线程与子线程会交替 (使用JConsole【操作:直接在控制台输入JConsole关键字即可启动~】可以展示线程的运行情况,证明main线程与子线程是在交替切换的)

线程的启动,run方法没有真正的启动线程,Start方法才是真正的启动了线程;

start()方法调用start0() 方法后,该线程并不一定立马执行,只是将线程变成了可运行状态,具体什么时候执行,取决于CPU,有CPU统一调度。

2.实现Runnable接口

  • 采用了静态代理模式

  • 启动方式

Dog dog = new Dog();
Thread t = new Thread (dog);
t.start();

线程的启动只能是调用start方法!!!!

Thread与Runnable的区别

  1. 继承Thread或者实现Runnable接口本质上没有区别,Thread类本身就实现 了Runnable接口
  2. 实现Runnable接口方式更加适合多个线程共享一个资源的情况,并且避免了单继承的限制,建议使用

对静态代理模式-代码演示

package JavaTest;

public class RunnableProxy {
    public static void main(String[] args) {
        Cat tiger = new Cat();
        ThreadProxy threadProxy = new ThreadProxy(tiger);
        threadProxy.run();
    }
}
class ThreadProxy implements Runnable {
    private Runnable target =null; // 属性,类型是Runnable类型

    @Override
    public void run() {
        if(target != null) {
            target.run(); // 动态绑定
        }
    }

    public ThreadProxy(Runnable target) {
        this.target = target;
    }

    public void start() {
        start0();
    }
    public void start0() {
        run();
    }
}

线程终止

  1. 满足条件退出
  2. 在指定条件退出线程循环

线程的常用方法

  1. setName // 设置线程名
  2. getName // 获取线程名
  3. start // 执行线程,底层调用的是start0方法
  4. run // 调用线程对象run方法
  5. setPriority // 获取线程优先级
  6. getPriority // 设计线程优先级
  7. sleep // 休眠
  8. interrupt // 中断线程 ,中断线程的休眠状态

第二组方法

  1. yield:线程的礼让,让出cup的时间,让其他线程执行,但是礼让的时间不确定,所以不一定礼让成功。
  2. join: 线程的插队,插队的线程一单插队成功,则肯定先执行完插队的线程所有内容

用户线程与守护线程

用户线程:工作线程,当线程的任务执行完或者通过方式结束

守护线程:为工作线程服务,当所有用户线程结束,守护线程自动结束

常见:垃圾回收器

public class ThreadTest2 {
    public static void main(String[] args) throws InterruptedException {
        MyDeamonThread mdt = new MyDeamonThread();
        // 将mdt设置为守护线程,当所有线程结束后,mdt也自动结束
        // 如果没有设置,那么及时main线程执行完毕,mdt也不退出
        mdt.setDaemon(true);
        mdt.start();
        for (int i = 0; i < 10; i++) {
            Thread.sleep(1000);
            System.out.println("宝强在辛苦工作,不知道马蓉在~");
        }
        //
    }
}

class MyDeamonThread extends Thread {

    @Override
    public void run() {
        for (; ; ) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("马蓉和宋喆在谋划~");
        }
    }
}

线程的寿命周期

线程的执行状态.png

  1. New(新建)
  2. Runnable(可运行) (Ready:等待被调度,Running:运行中)
  3. Blocked(阻塞)
  4. Waiting(等待)
  5. Timed Waiting(超时等待)
  6. Terminated(终止)