-
线程简介
- 用户既可以使用计算机听歌,也可以使用它打印文件,而这些活动完全可以同时进行,这种思想放在Java中被称为并发,而将并发完成的每一件事情称为线程。
- Java语言提供并发机制,程序员可以在程序中执行多个线程,每一个线程完成一个功能,并与其他线程并发执行,这种机制被称为多线程。
-
实现线程的两种方式
继承Thread类
Thread类是java.lang包中的一个类,从这个类中实例化的对象代表线程,程序员启动一个新线程需要建立Thread实例
Thread类中常用的两个构造方法如下:
- public Thread(String threadName);
- public Thread();
- 其中第一个构造方法是创建一个名称为threadName的线程对象。
- 继承Thread类创建一个新的线程的语法如下:
- public class ThreadTest extends Thread{
//...
}
实现Runnable接口
- 线程都是通过扩展Thread类来创建的,如果程序员需要继承其他类(非Thread类)并使该程序可以使用线程,就需要使用Runnable接口
- 如:一个扩展JFrame类的GUI程序不可能再继承Thread类,因为Java语言中不支持多继承,这时该类就需要实现Runnable接口使其具有使用线程的功能
实现Runnable接口语法:
public class Thread extends Object implements Runnable
-
线程的生命周期
线程具有生命周期,其中包含7种状态,分别为:
- 出生状态:用户在创建线程时处于的状态,在用户使用该线程实例调用start()方法之前线程都处于出生状态
- 就绪状态:当用户调用start()方法后,线程处于就绪状态(又被称为可执行状态)
- 运行状态:当线程得到系统资源后就进入运行状态
- 等待状态
- 休眠状态
- 阻塞状态
- 死亡状态
-
操作线程的方法
- 线程的休眠
控制线程行为的方法是调用sleep()方法,sleep()方法需要一个参数用于指定该线程休眠的时间,该时间使用毫秒为单位
sleep()方法的语法如下:
try{
Thread.sleep(2000);
}catch(InterruptedException e){
e.printStackTrace();
}
在run()方法内的循环中被使用
- 线程的加入
- 当某个线程使用join()方法加入到另外一个线程时,另一个线程会等待该线程执行完毕再继续执行
- 举例:一个人正在看电视,却突然有人上门收水费,读者必须付完水费后才能继续看电视
- 线程的中断
- 过去的jdk版本使用stop()方法停止线程,现在已经废除
- 现在提倡在run()方法中使用无限循环的形式,然后使用一个布尔型标记控制循环的停止
- 线程的礼让
- yield()方法实现线程礼让只是给当前正处于运行状态下的线程一个提醒,告知它可以将资源礼让给其他线程,但这仅仅是一种暗示,没有任何一种机制保证当前线程会将资源礼让
- yield()方法使具有同样优先级的线程有进入可执行状态的机会,当当前线程放弃执行权时会再度回到就绪状态。对于支持多任务的操作系统来说,不需要调用yeild()方法,因为操作系统会为线程自动分配CPU时间片来执行
-
线程的优先级
- 每个线程都具有各自的优先级,线程的优先级可以在程序中表明该线程的重要性,
- 如果有很多线程处于就绪状态,系统会根据优先级来决定首先使哪个线程进入运行状态。但这并不意味着低优先级的线程得不到运行,而只是它运行的几率比较小
- 比如垃圾回收线程的优先级就较低
- Thread类中包含的成员变量代表了线程的某些优先级,比如Thread.MIN_PRIORITY(常数1)、Thread.MAX_PRIORITY(常数2)、Thread.NORM_PRIORITY(常数5)。其中每个线程的优先级都在Thread.MIN_PRIORITY~Thread.MAX_PRIORITY之间,在默认情况下其优先级都是Thread.NORM_ PRIORITY。每个新产生的线程都继承了父线程的优先级。
-
同步线程
线程安全
线程安全的实质:线程安全问题来源于两个线程同时存取单一对象的数据
线程同步机制
两件事情不能同时做
一次只执行一个线程