1 🚩基本概念
程序(program):就是我们写的代码;
进程:运行的程序;是程序的一次执行过程,存在有产生、存在、消亡等;
线程:由进程创建,是进程的一个实体;
单线程:同一时刻只允许执行一个线程:
多线程:同一时刻允许执行多个线程;如用下载软件可同时下载多个资源
并发:同一时刻多个任务交替执行,单核CPU执行多任务就是并发;
并行:同一时刻,执行多个任务,多核CPU执行多个任务;
2 🚩线程的基本使用
在java中线程使用有两种方法,分别是
①继承Thread的类,重写run方法;
②实现Runnable接口,重写run方法;
2.1 线程的使用方式1 继承Thread类,重写run方法
2.2 线程的使用方式2 实现Runnable接口,重写run方法
两种方法的使用示例:
public class TestRunnable2 { public static void main(String[] args) { // 创建PrintHello对象 PrintHello pho = new PrintHello(); // 创建PrintHai对象 PrintHai ph = new PrintHai(); // 继承Thread类对象启动线程 pho.start(); // 实现Runnable接口类对象,启动线程 Thread td = new Thread(ph); td.start(); } } //PrintHai类实现Runnable接口 class PrintHai implements Runnable{ // 重写run方法 @Override public void run() { // 在run方法内写需要执行的代码 int count = 0; while (true){ System.out.println("HiHi"+Thread.currentThread().getName()+"计数:"+count); count++; try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } if (count==10)break; } } } //PrintHello 继承Thread类 class PrintHello extends Thread{ //重写run方法 @Override public void run() { // 在run方法中写执行的代码 int count = 0; while (true){ System.out.println("hello"+Thread.currentThread().getName()+"计数:"+count); count++; try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } if (count==60)break; } } }
2.3 终止线程
(1) 线程完成任务以后自动退出
(2)通过变量来控制run方法退出,进而控制线程
3 🚩线程常用的方法
方法名 | 说明 |
setName | 设置线程名称,使之与参数名相同 |
getName | 返回线程名 |
start | 开启线程,JVM调用该线程start0方法 |
run | 调用线程对象run方法 |
setPriority | 更改线程优先级 |
getPriority | 获取该线程优先级 |
sleep | 指定毫秒数让当前正在执行的线程休眠 |
interruput | 中断线程 |
常用方法2
yield方法,礼让但不一定成功;
join方法,插队,一旦插队成功必先执行完所有插队任务再
4 🚩用户线程和守护线程:
用户线程:也叫工作线程,当线程任务执行完毕或收到通知才结束;
守护线程:一般为工作线程服务,当所有用户线程结束,守护线程自动结束;
常见的守护线程:垃圾回收机制;
5 🌰用户线程与守护线程代码示例
class MainTest2{ public static void main(String[] args) throws InterruptedException { MyDeamon txc = new MyDeamon(); Thread td = new Thread(txc); // 将线程设计为守护线程;当所有用户线程结束后,守护线程自动结束 td.setDaemon(true); // 启动子线程 td.start(); // 设置主线程 for (int i = 0; i < 6; i++) { System.out.println("主线程" + Thread.currentThread().getName() + "执行了" + i + "次"); // if (i == 5){ // td.join(); // } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } //子线程 class MyDeamon implements Runnable{ @Override public void run() { int count = 0; while (true) { System.out.println("子线程" + Thread.currentThread().getName() + "执行了" + count + "次"); count++; try { Thread.sleep(1000); if (count == 20)break; } catch (InterruptedException e) { e.printStackTrace(); } } } }
6 🚩线程的生命周期
线程有六种存在状态:
线程状态。线程可以处于以下状态之一:
NEW尚未启动的线程处于此状态。
RUNNABLE在Java虚拟机中执行的线程处于此状态。
BLOCKED被阻塞等待监视器锁定的线程处于此状态。
WAITING无限期等待另一个线程执行特定操作的线程处于此状态。
TIMED_WAITING正在等待另一个线程执行最多指定等待时间的操作的线程处于此状态。
TERMINATED已退出的线程处于此状态。
7 🚩线程同步
线程同步机制:
保证在同一时刻数据最多允许,只有一个线程访问,保证数据的完整性;
7.1 同步的实现步骤
使用Synchronized(互斥锁)
(1)同步代码块
//得到对象的锁才能操作,同步同步代码块
synchronized(对象){
//同步代码块
}
(2)放在方法声明中,表示整个方法为同步方法;
7.2 释放锁
释放锁的条件:
(1) 当线程的同步方法,同步代码块执行结束;
(2)当前线程在同步代码块、同步方法中遇到break、return会
(3)当前线程在同步代码块、同步方法中出现了未处理的Error、Exception;
(4)当前线程在同步代码块、同步方法中执行了线程对象的wait方法,当前线程暂停并释放锁;
不会释放锁的几种情况;
(1)线程在执行同步代码块同步方法时,程序调用了Thread.sleep()、Thread.yield()方法,暂停当前线程执行,但是不会释放锁;
(2)线程执行同步代码块时,其他线程调用了当前线程的suspend()方法将该线程挂起,该线程不会释放锁;