一.实现Runnable接口方式
首先是过程中碰到的问题,出现问题的原因和解决办法:
问题 | 描述 | 原因 | 解决方法 |
---|---|---|---|
1 | 同一张票被多次卖出 | 一个线程打印了卖出第1000张,还没执行ticket - -,另一个线程就进来执行打印卖出第1000张票。 | 加锁 |
2 | 卖出第负数张票 | 最后一张票卖出时,ticket的值变为0,但此时其他的线程已经在循环内,它们在ticket=0之前就已经等在while循环内、锁区外了,所以ticket=0后它们还会继续各执行一次锁区内的代码,也就会打印出负数了。 | 在锁区内执行打印之前判断ticket的值。 |
3 | 个别线程未打印“票已卖完” | while(ticket > 0)把个别线程挡在了外面,无法执行到打印“票已卖完”。 | while(ticket > 0)改为while(true),在打印“票已卖完”后用break退出循环。 |
锁
主要考虑的两个问题:
1.----注意锁的对象:必须要是同一个对象
2.----注意锁的范围:不需要锁的不要锁
锁的分类
1.同步代码块
2.同步方法
3.对象互斥锁
代码
package com.qf.a_task;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 售票
* @author Zhouzilong
* @date 2019年8月13日
*/
public class TaskTest {
public static void main(String[] args) {
//五个线程操作一个任务对象,若循环中是new Thread(new Task());则是每个线程分别操作一个任务对象,相当于卖5倍数量的票
Task task = new Task();
for (int i = 1; i <= 5; i++) {
new Thread(task,"窗口00"+i).start();
}
}
}
class Task implements Runnable{
private int ticket = 10;
//实例化互斥对象锁
private Lock lock = new ReentrantLock();
//方式3:对象互斥锁 ---容易出现死锁
/*@Override
public void run() {