第十一章、java线程
支线程类得定义需要继承Thread类或是实现Rannable接口,其中的run方法相当于之线程的main方法,通过start方法启动支线程
线程的几种状态
Thread类
run()
主线程中的main方法
start()
在主线程中启动支线程的方法
Sleep()
静态方法,暂停时间
getName()
setName()
获取设置线程名字
getId()
获取线程ID
join()
重载方法。可以设置等待调用此方法的线程的执行时间
t.join(3000);//如果调用此方法的线程在3秒内执行完毕,则在此线程执行完毕后在往后走,但是如果在3秒内没有执行完毕,则不管此线程当前线程继续往下走
t.join();//不管此线程执行多久,一定要等待调用此方法的线程执行完毕之后再往后执行
setPriority()
设置线程优先级,最低为1,最高为10
currentThread()
静态方法,获取当前线程对象
Runnable接口
解决了单继承的问题(如果继承Thread则不能继承别的类。但是实现Runnable接口可以继承别的类,也可以实现别的接口),只有一个抽象run方法。
需要通过Thread的包装来启动线程
public class TestRunnable implements Runnable{}
Thread t = new Thread(new TestRunnable());
t.start();
synchronized锁
1、直接修饰方法
public synchronized void add(){}
可以作为修饰符,当作为修饰符的时候,自动使用this为钥匙,只有获取到此钥匙才能打开这把锁进去操作
2、传入一个锁对象,将代码快锁住
synchronized(){}
synchronized(Object){
}
被synchronized包裹的代码快,是一个整体部分只有执行完毕这一个整体部分的代码才会释放钥匙
通知机制
Object的关于锁的方法
wait()
obj.wait();//暂时释放锁,并进入等待状态
暂时释放锁,并进入等待状态(有重载方法,等待指定时间内)
notify()
obj.notify();//通知对象监听器上的单个线程锁已经释放了
通知一个对象监听器锁已经释放了
notifyAll()
obj.notifyAll();//同知此对象监听器上的所有线程,锁已经释放
同知此对象监听器上的所有线程,锁已经释放
进程与线程
进程是系统分配资源的最小单位,线程是程序执行的最小单位
进程是由一个或多个线程组成,线程是一个进程中代码执行的不同路线
进程之间相互独立,但是线程之间共享资源
并发与并行
多个程序都在已进入已启动和运行完毕之间,他们暂用CPU的不同时间段资源
系统有一个或多个CPU时,多个程序占用不同的CPU资源,多个程序每个时间段都在运行。
异步与同步
同步是先将操作执行完毕之后再去将结果返回(响应),异步是先将结果返回(响应)再去执行操作
死锁
是线程A获取了a锁,线程B获取了b锁,线程A在获取了a锁之后还想去获取b锁,线程B在获取了b锁之后去获取a锁,造成了线程之间相互等待,从而进入死锁状态
解决方法
线程使用钥匙的wait方法进入等待状态,待另一个线程使用完a锁之后使用钥匙的notifyAll通知a锁对象监听器上的所有线程锁已经释放
重量级锁
像系统申请互斥资源,将进程进行阻塞和恢复
自旋锁
适用锁粒度小(竞争时间小)在锁被使用的轻快下自旋(类似for循环),如果在自旋时间内申请到了锁,则省去了阻塞和恢复进程的时间
自适应自旋锁
适用竞争时间不固定,竞争激烈,根据上一次自旋得到锁的时间来定义自旋时间,初始化时间不好设置
轻量级锁
不申请互斥量,使用竞争不激烈,Mark Word中的部分字节CAS更新指向线程栈中的Lock Record,如果更新不成功则升为重量级锁
偏向锁
在没人竞争或是一个线程使用的情况下。只需要在Mark Word中CAS记录owner(本质上也是更新,但初始值为空),如果记录成功,则偏向锁获取成功,记录锁状态为偏向锁