第8章 线程
线程可以让一个程序同时执行多个任务,在实际程序应用地非常广泛。
8.1 理解线程
8.1.1进程的概念
了解线程前先了解一下进程,进程可以看成是程序的执行,可以把一个程序的执行过程看成是一个进程。
比如我们打开一个Word程序,就有一个Word程序进程。
8.1.2 线程的概念(此处是个人理解。)
一个进程可以有多个线程,同时执行多个任务。同样用Word举例,Word显示可以看成是一个线程,编辑可以看出是一个线程。
8.1.3 线程的生命周期
线程的生命周期有4种基本状态:
1.产生
2.中断
3.非中断(运行或可运行)
4.退出
8.2 线程类设计
8.2.1 线程API类图
Thread类是线程实现的主类,其核心过程方法由Runnable接口规范。
8.2.2 线程类Thread的构造方法
1.Thread(String threadName); //创建指定名称的线程类
2.Thread(); //线程类名称系统自动指定Thread-编号
3.Thread(Runnable target) //target为目标对象,target需要实现Runnable接口,给出run()方法。
8.3 线程实现
线程的实现一般有两种方式:
(1)创建Thread类的子类,并重新定义run()方法,用户只要创建子类对象就能建立自己的线程。
(2)创建实现Runnable接口的类,并实现run()方法。
8.3.1 继承实现
方式一:继承Thread类
8.3.2接口实现
方式二:实现Runnable接口
8.4 线程控制
8.4.1 监控线程状态
线程状态在枚举类型Thread.State中定义。
NEW:新创建,还没调用start()
RUNNABLE:run()中代码被执行
BLOCKED:阻塞,等待解锁
WAITING:另一个线程运行,本线程等待
TIMED_WAIYING:等待到指定时间
TERMINATED:线程退出run()
获取线程状态方法:
public Thread.State getState()
8.4.2 线程休眠
Thread的sleep()方法
注意:(1)sleep是静态方法,睡眠的是当前运行的线程、
8.4.3 中断线程
public void interrupt() :中断当前阻塞与等待状态,强制线程抛出异常。
8.4.4 阻塞进程 join()
void join(): 当前线程等待加入该线程后面,等待该线程终止
void join(long millis):当前线程等待该线程终止的时间最长为millis毫秒,如果超时还没执行完,当前线程也会进入就绪状态。
void join(long millis, int nanos);等待时间millis毫秒+nanos纳秒
8.4.5线程等待和唤醒
如果线程等待用sleep(),唤醒用interrupt()
等待用join(),唤醒用interrupt()
等待用wait(),唤醒用notify();
8.4.6线程终止
当前线程放弃调度执行权力,等待下次排队执行。
public static void yield()
..线程控制综合实例
8.5 线程属性
8.5.1 优先级
优先级较高的线程获取CPU资源的概率较大。
每个线程默认的优先级和父线程相同。
Thread类提供setPriority(int newPriority和getPriority)和getPriority()方法来设置和得到优先级。
setPriority的参数时一个整数,范围1~10. (10最高)。
优先级实例:
多次运行可以发现,多数情况下优先级高的先运行完成。
8.5.2 守护线程
Java中有两类线程:用户线程User Thread 和 守护线程Daemon Thread
守护线程具有最低优先级,为系统其它对象提供服务。
一般不会自己操作守护进程。
8.6线程同步
8.6.1Synchronized同步方法和同步代码块
保护某段代码只能同时被一个线程执行的技术成为线程同步。
关键字synchronized是Java内部实现的一个简单锁,可以用synchronized锁定一段代码:
或者锁定整个方法:
8.6.2 同步变量volatile关键字
Java变量前可以加修饰语volatile,volatile的主要目的是解决成员变量的多线程访问同步问题。
在读取加了volatie修饰的变量时,会直接从内存读取。
但volatile不保证对变量的操作是原子操作。
Java提供java.util.concurrent.automic包,提供了基本类型与引用类型的原子性操作封装类:
AtomicBoolean
AtomicInteger
AtomicIntegerArray
...
8.6.3线程锁Lock接口及ReentrantLock类
...
8.6.4 死锁
不同线程都在等待那些不可能被释放的锁时,就成了死锁。
构成死锁的典型是锁交叉。