目录
1、什么是线程
程序
一个特定功能的代码
进程
程序运行的过程,有生命周期
线程
进程中运行的路径,可有多条
并行
有多个内核实现,同一时刻执行多个线程
并发
单内核,在一定的时间片段内,CPU交替执行多条线程,当CPU去执行一个线程之时,其他线程处于就绪状态??
2、线程的创建
继承Thread
步骤
1、创建类去继承Thread类
2、实现、重写Thread类中的run()方法,线程的操作需要写入run方法中
3、在主方法中实例化继承Thread类的类的对象
4、通过该对象去调用start()方法来启动线程和运行run()方法
注意点
”对象.start()“只能调用一次,否则会抛除非法线程异:IllegalThreadStateException
不能“对象.run()”,此时执行的是普通的run方法,并没有线程的产生
实现接口Runnable
好处
相对于Thread而言,突破了类单继承的局限。
当多个线程共享同一份资源时,Runnable更好操作。
步骤
1、创建类去实现Runnable接口。
2、类中实现run()方法,线程操作写在run方法中
3、创建实现Runnable接口的实例化对象
4、创建Thread类的对象,并将实现了Runnable接口的对象赋值给Thread对象的构造器中
5、通过Thread的对象去调用start方法,从而启动线程和run方法
实现接口Callalbe
1、创建类去实现Callable接口
2、在实现类中实现call()方法,并把线程操作放入call方法中
3、创建Callable接口实现类的对象
4、将此Callable接口实现类的对象专递到FutureTask构造器中,创建FutureTask的对象
5、将FutureTask的对象专递到Thread的构造器中,创建Thread的对象
6、通过对象.start()的方式,启动线程
7、想要获取返回值时,可以调用FutrueTask类的对象.get()
有返回值,会抛异常,可以在外部获得捕获异常
线程池
步骤
1、提供固定线程数量的线程池
2、执行特定的线程操作,需要提供实现Runnable接口或Callable接口的类的对象
好处
避免了线程的反复创建、运行、销毁,从而耗费大量资源
提高了相应速度,从线程池中直接获取
降低了资源消耗
便于线程管理
3、线程的生命周期
新建
在Thread类或其子类被的对象被声明并创建时,新生的线程对象处于新建状态
就绪
在执行start方法后,该线程进入了等待CPU时间片的队列中,等待者获得CPU的运行,只是还没有获得运行资源而已
运行
获得时间片,获得CPU运行,run()方法定义了线程的操作和功能
结束
当线程完全完成了它的功能和操作后,或被强行终止或遇到异常导致结束
堵塞
在运行过程中,因特殊操作使得该线程处于无法被CPU调度的状态
4、线程的安全
死锁
多线程时,线程间互相拿着对方的锁,同步监视器不放,而对方也在等待着对方释放它所需的锁,从而进入僵持状态,形成死锁,没有报错,也没有异常,程序一直停留在某一个状态。
同步机制
同步监视器的存在
当线程处理共享资源时,线程必须拿着同步监视器才能获得共享资源,而其他的线程则需要等待锁的释放获得锁,从而一直等待者,从而做到共享资源的同步
操作方法
synchronized
同步代码块
synchronized(同步监视器){//被同步监视的代码块}
同步方法
权限 synchronized 返回值 方法名(){}
lock锁
java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具
ReentrantLock 类实现了 Lock
通过ReentranLock类的对象去调用lock方法,从而景象加锁和解锁
加锁:lock.lock()
解锁:lock.unlock()
如果同步代码有异常,要将unlock()写入finally语句块
异同
都实现了线程安全
synchronized在方法或代码块中,执行完相应区域后,会自动释放锁
而lock锁则需要手动调用unlock方法去释放
从而,使得lock锁更加灵活
5、线程的通信
wait()
对象.wait()进入阻塞状态,并释放共享资源、同步监视器对象,等待其他线程调用notify()或notifyAll()唤醒,才能重新获得CPU资源继续执行下去
notify()/notifyAll()
唤醒被wait的线程,notify()按优先级最高的唤醒,notifyAll()唤醒所有
这三个方法只能在synchronized中使用,它们由对象同步监视器调用
Thread类的方法
setName
设置线程名称
getName
返回线程名称
start
启动线程并运行run方法
run
线程被调度时执行的操作
currentThread
返回当前线程。在Thread子类中就 是this,通常用于主线程和Runnable实现类
yield
线程让步
暂停当前正在执行的线程,把执行机会让给优先级相同或更高的线程
线程执行同步代码块或同步方法时,程序调用Thread.sleep()、 Thread.yield()方法暂停当前线程的执行
sleep(long millis)
使当前线程在指定时间内失去对CPU资源的获取,进入阻塞状态,等待时间结束,才能有资格获取CPU资源
join()
使用该方法,可使当前线程阻塞,执行其它线程,等待join()进来的线程执行结束后,当前线程才能继续执行
stop
强制结束线程生命周期
isAlive
判断线程是否还存