共享资源的安全
使用线程运行多个任务时,可以通过加锁(互斥)来保证共享资源的安全。jdk5以后主要有两种方式,synchronized和lock。
wait和notify
在保证线程安全访问共享资源后,我们要思考,多个线程之间的协作的问题。
比如我们生活中的炒菜,炒菜之前要把菜切好,并且把相关的调料准备好,才能开始炒菜。这样,线程之间就有了依赖关系。
java里面提供了wait和notify来实现线程的协作。
wait等待线程里的某个条件发生变化,而改变这个条件超出了这个线程的能力。通常,要由另一个线程来改变。
notify主要功能是唤醒在等待种的线程。
比如上面炒菜,同时启动了炒菜线程和切菜线程,但是炒菜线程启动要,要等待切菜线程执行完,然后通知炒菜线程,炒菜线程才会接着执行。
wait和sleep的区别
- wait期间锁是释放的,而sleep是不会释放任务资源。
简单线程协作的示例
两个任务:一个任务将腊涂在Car上,一个是抛光它。抛光任务在涂蜡任务完成之前是不能执行的,而涂蜡任务在另一次涂蜡之前,要等待抛光完成。
public class Car {
/**
* 标识位
*/
private boolean waxOn = false;
public synchronized void waxed(){
//修改标识位为true,表示可以打蜡了
waxOn = true;
//唤醒打蜡的线程
notify();
}
public synchronized void buffed(){
//修改表示为false,表示可以抛光了
waxOn = false;
//唤醒抛光线程
notify();
}
public synchronized void waitingToWax() throws InterruptedException{
//当waxOn为false的时候,打蜡线程阻塞
if(waxOn == false){
wait();
}
}
public synchronized void waitingToBuffed()throws InterruptedException{
//当waxOn为true的时候,抛光线程阻塞
if(waxOn == true){
wait();
}
}
}
/**
* @Auther: allen
* @Date: 2019/10/13 14:52
* @Description:打蜡线程
*/
public class WaxOn implements Runnable{
private Car car;
public WaxOn(Car car) {
this.car = car;
}
public void run() {
try {
while (!Thread.interrupted()) {
System.out.println("Wax On!");
TimeUnit.MILLISECONDS.sleep(200);
//通知涂蜡结束,并且阻塞抛光线程
car.waxed();
car.waitingToBuffed();
}
} catch (Exception e) {
System.out.println("WaxOn interrupted.")
}
}
}
/**
* @Auther: allen
* @Date: 2019/10/13 14:55
* @Description:抛光线程
*/
public class WaxOff implements Runnable{
private Car car ;
public WaxOff(Car car) {
this.car = car;
}
public void run() {
try {
while (!Thread.interrupted()){
System.out.println("Wax off!");
TimeUnit.MILLISECONDS.sleep(200);
//通知抛光结束,并且阻塞打蜡线程
car.buffed();
car.waitingToWax();
}
} catch (Exception e) {
System.out.println("WaxOff interrupted.")
}
}
}
/**
* @Auther: allen
* @Date: 2019/10/13 14:57
* @Description:
*/
public class WaxOnMatic {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
Car car = new Car();
exec.execute(new WaxOn(car));
exec.execute(new WaxOff(car));
try {
TimeUnit.MILLISECONDS.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
exec.shutdownNow();
}
}
执行结果:WaxOn和WaxOff是交替输出。
Wax On!Wax off!Wax off!Wax On!Wax off!Wax On!Wax off!
Wax On!Wax off!Wax On!Wax off!Wax On!Wax off!Wax On!
Wax off!Wax On!Wax off!Wax On!Wax off!Wax On!Wax off!
Wax On!Wax off!Wax On!Wax off!Wax On!