Bootstrap

Java之多线程基础

一、进程

进程指运行中的程序,占用一定的内存空间。存在自身的生命周期。

二、线程

线程由进程创建,是一个进程的实体。一个进程可以拥有多个线程。

1、单线程

同一时刻,只允许执行一个线程

2、多线程

同一时刻,可以执行多个线程。【比如:迅雷同时下载多个文件】。主线程挂了,如果还有子线程存在,整个应用程序【进程】还存活着。

3、创建线程类的两种方法

3.1、继承Thread类,重写run方法

Thread底层也是继承了Runnable接口,从而重写了Runnable接口的run方法。

Cat cat = new Cat();
cat.start(); // 调用线程类重写的run方法, 让线程变为可运行状态
3.2、实现Runnable接口,重写run方法

Java是单继承的,如果已经继承了其他类,该类可以实现Runnable接口来创建线程类。适合多个线程共享一个资源:即是多个Thread对象绑定同一个线程对象。

Cat cat = new Cat();
// 代理模式: Runnable接口是没有start方法的  可以传入Runnable类型的对象给Thread类, 
// 通过动态绑定,实现   Runnable类型的对象.start()
Thread thread = new Thread(cat);
thread.start(); // 调用线程类重写的run方法, 让线程变为可运行状态

4、为什么启动线程是start(),而不是直接调用重写的run方法

如果直接在某一个线程里调用run方法,只是通过实例对象调用的线程类的普通方法run,而并没有真正的启动一个线程,此时会阻塞原本的线程,需要把run执行完毕,才会向下执行。真正实现多线程的是start方法底层的start0方法,start0方法由JVM调用。调用了start后,线程并不会立马执行,只是具备了运行状态,线程的生命周期由CPU决定,而不是start方法。

5、线程的常用方法

  • setName: 设置线程名称
  • getName: 返回该线程的名称
  • start:使线程进入可运行状态
  • setPriority: 设置线程优先级
  • sleep: 在指定的毫秒数内,让正在执行的线程休眠
  • interrupt: 中断线程的休眠状态
  • yield:礼让调用该方法的线程。能否成功礼让,由CPU决定。未必会礼让成功。
  • join:让调用该方法的线程插个队,插队的线程执行完后,在执行其他线程。一定会插队成功。

6、用户线程

也叫工作线程,当线程的任务执行完成或者通知方式结束

7、守护线程

一般是为工作线程服务的,当其他所有的用户线程结束,守护线程自动结束

7.1、常见的守护线程:

垃圾回收机制

7.2、普通线程设置成守护线程
// 需要写在start方法之前
线程实例化对象.setDaemon(true);

8、线程的七种状态

在这里插入图片描述
在这里插入图片描述

Thread

9、线程同步机制

线程同步:当有一个线程对内存进行操作时,其他线程都不能对这个内存地址操作,需要等待排队。

10、线程死锁

多个线程竞争同一把锁,从而造成死锁,导致线程进入阻塞状态。

10.1、什么时候释放锁
  1. 当前线程的同步方法/同步代码块执行结束
  2. 当前线程在同步代码块/同步方法中遇到break、return
  3. 当前线程在同步代码块/同步方法中出现了未处理的异常,导致异常结束
  4. 当前线程在同步代码块/同步方法中执行了wait方法,当前线程暂停,并释放锁
10.2、以下情况不会释放锁
  1. 程序调用Thread.sleep()、Thread.yield(): 暂停当前线程,不会释放锁;
  2. 线程执行同步任务时,其他线程调用了该线程的suspend方法是,该线程挂起,该线程不会释放锁。

三、并发

同一时刻,多个任务交替进行。单核CPU实现多任务

四、并行

同一时刻,多个任务同时进行。多核CPU可以实现并行和并发同时存在。

1、查看电脑CPU的个数 【核数】

Runtime runtime = Runtime.getRuntime();
int count = runtime.availableProcessors();
;