JAVA - 线程

发布于:2022-11-08 ⋅ 阅读:(966) ⋅ 点赞:(0)

一、进程

进程是正在运行的程序

  • 是系统进行资源分配调用独立单位
  • 每一个进程都有它自己的空间系统资源

二、线程

线程是进程中的单个顺序控制流,是一条执行路径

  • 单线程:一个进程 如果只有一条执行路径,则称其为单线程
  • 多线程:一个进程如果有多条执行路径,则称其为多线程

2.1 多线程的实现方式

方式一:继承 Thread

  • 在类中重写 run() 方法;(run方法是用来封装被线程执行的代码);
  • 启用 start() 方法;(start方法用于启动线程,然后由JVM调用此线程的run方法);

方法二:实现 Runnable 接口

  • 在类中重写 run() 方法;
  • 创建 Thread 类的对象将实现 Runnable 的类对象作为构造方法内的参数传入;

相比于继承 Thread 类,实现 Runnable 接口的好处:

  • 避免了 Java 单继承的局限性;
  • 适合多个相同程序的代码去处理同一个资源的情况,把线程和程序的代码、数据有效分离,较好的体现了面向对象的设计思想;

2.2 设置和获取线程名称

Thread类中设置和获取线程名称的方法

  • void setName(String name):将此线程的名称更改为参数 name
  • String getName():返回此线程的名称;
  • 通过构造方法也可以设置线程名称;

获取 main() 方法所在线程的名称:

  • public static Thread currentThread(): 返回对当前正在执行的线程对象的引用;

2.3 线程调度

线程调度有两种调度模型:

  • 分时调度模型:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片;
  • 抢占式调度模型:优先让优先级高的线程使用 CPU ,如果线程的优先级相同,那么就会随机选择一个(多线程程序的随机性),优先级高的线程获取 CPU 时间片相对多一些;

JAVA 使用的是抢占式调度模型;

Thread 类中设置和获取线程优先级的方法

  • public final int getPriority(): 返回该线程的优先级;
  • public final void setPriority(int newPriority): 更改此线程的优先级;
  • 线程的优先级默认值是 5
  • 线程优先级的范围是:1 - 10
  • 线程优先级高仅仅表示线程获取的 CPU 时间片的几率高,但是要在次数比较多,或者多次运行的时候才能看到你想要的效果;

2.4 线程控制

  • static void sleep(long millis): 使当前正在执行的线程停留(暂停执行)指定的毫秒数;
  • void join(): 等待这个线程死亡;
  • void setDaemon(boolean on): 将此标记为守护线程,当运行的线程都是守护线程时,java 虚拟机将退出;

2.5 线程的生命周期

线程的生命周期一共分为五个部分分别是:新建就绪运行阻塞以及死亡

  • 新建状态是指新创建一个线程对象;
  • 就绪状态是指一个进程有执行资格但是没有抢到 CPU 的执行权;
  • 运行状态是指有执行资格并抢到执行权;
  • 阻塞状态是指没有执行资格也没有执行权;
  • 死亡状态是指线程结束;(可能是run()方法内执行完毕,也可能是被stop()方法终止运行);

三、同步代码块

使多个操作共享数据,可以使用同步代码实现

  • 格式
synchronized(任意对象){
	多条操作共享数据的代码;
}
  • synchronized(任意对象):就相当于给代码加锁了,任意对象就可以看成是一把锁;

同步的好处和弊端

  • 好处:解决了多线程的数据安全问题;
  • 弊端:当线程很多时,因为每一个线程都会去判断同步上的锁,这会耗费很多不必要的时间,无形中降低程序的运行效率;

3.1 同步方法

同步方法:把 synchronized 关键字加到方法上

  • 格式:

修饰符 synchronized 返回值类型方法名(方法参数){ }

同步方法的锁对象是:this

同步静态方法:把 synchronized 关键字加到静态方法上

  • 格式

修饰符 static synchronized 返回值类型方法名(方法参数){ }

同步静态方法的锁对象是:类名.class

3.2 线程安全的类

StringBuffer

  • 线程安全,可变的字符序列
  • 从版本 JDK5 开始,被 StringBuilder 替代,通常应该使用 StringBuilder 类,因为它支持所有相同的操作,但它更快,因为它不执行同步;

Vector

  • Java2平台v1.2 开始,该类改进了 List 接口,使其成为 Java Collections Framework 的成员,与新的集合实现不同,Vector 被同步,如果不需要线程安全的实现,建议使用 ArrayList 代替 Vector

Hashtable

  • 该类实现了一个哈希表,它将键映射到值,任何非 null 对象都可以用作键或者值;
  • Java2平台v1.2 开始,该类进行了改进,实现了 Map 接口,使其成为 Java Collections Framework 的成员,与新的集合实现不同, Hashtable 被同步,如果不需要线程安全的实现,建议使用 HashMap 代替 Hashtable

3.3 Lock锁

为了更清晰的表达如何加锁和释放锁, JDK5 之后提供了一个新的锁对象 Lock

Lock 实现提供比使用 synchronized 方法和语句可以获得更广泛的锁定操作;

Lock 中提供了获得锁和释放锁的方法

  • void lock(): 获得锁;
  • void unlock(): 释放锁;

Lock 是接口不能直接实例化,Lock 需要使用它的实现类 ReentranLock 来进行实例化;

3.4线程等待和唤醒方法

  • void wait(): 导致当前线程等待,直到另一个线程调用该对象的 notifynotifyAll 方法;

  • void notify(): 唤醒正在等待对象监视器的单个线程;

  • void notifyAll(): 唤醒正在等待对象监视器的所有线程;

本文含有隐藏内容,请 开通VIP 后查看