JAVA - 线程
一、进程
进程是正在运行的程序
- 是系统进行资源分配和调用的独立单位;
- 每一个进程都有它自己的空间和系统资源;
二、线程
线程是进程中的单个顺序控制流,是一条执行路径
- 单线程:一个进程 如果只有一条执行路径,则称其为单线程;
- 多线程:一个进程如果有多条执行路径,则称其为多线程;
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(): 导致当前线程等待,直到另一个线程调用该对象的 notify 或 notifyAll 方法;
void notify(): 唤醒正在等待对象监视器的单个线程;
void notifyAll(): 唤醒正在等待对象监视器的所有线程;
本文含有隐藏内容,请 开通VIP 后查看