package test;
import java.util.List;
/**
* @Author:txd
* @Date:2022/9/17
* @Description:
*/
public class tickets {
public static void main(String[] args) {
TicketThread ta=new TicketThread();
Thread t1=new Thread(ta,"窗口1");
Thread t2=new Thread(ta,"窗口2");
Thread t3=new Thread(ta,"窗口3");
Thread t4=new Thread(ta,"窗口4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class TicketThread implements Runnable{
private int redundNum;
private int sellTikcetsNum=100;
@Override
public void run() {
while (true){
try {
sellTicket();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void sellTicket() throws InterruptedException {
String threadName=Thread.currentThread().getName();
if(sellTikcetsNum>0){
//退票条件:窗口4,票数小于100,满足一定概率
if(threadName.equals("窗口4") && sellTikcetsNum<100 && Math.random()<0.5) {
if(redundNum>4){
this.wait();
}
sellTikcetsNum++;
redundNum++;
System.out.println("退票张数" + redundNum + "总票数" + sellTikcetsNum);
//卖票条件:窗口1,2,3
}else if(threadName.equals("窗口1") ||threadName.equals("窗口2") ||threadName.equals("窗口3")){
sellTikcetsNum--;
System.out.println(Thread.currentThread().getName()+"售卖票数的编号"+sellTikcetsNum);
}
Thread.sleep(1000);
}
}
}
package com.duoxiancheng;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* @Author:txd
* @Date:2022/9/15
* @Description:
*/
public class onrHundredPrint {
public static void main(String[] args) throws InterruptedException {
Task2 t = new Task2();
Thread t1 = new Thread(t,"A");
Thread t2 = new Thread(t,"B");
t1.start();
t2.start();
}
}
// class Task implements Runnable{
// private int number = 0;
// private ReentranLock lock = new ReentranLock();
// private Condition condition = lock.newCondition();
//
// @Override
// public void run(){
// while(number<100){
// lock.lock();
// number++;
// condition.signal();
// try{
// if(number<100)
// condition.await();
// }catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// }
// }
//假设A线程先获得锁,B会阻塞(同步队列),A第一次调用signal(),但此时条件队列为空,firstWaiter为null,
//然后A调用await(),让出锁,同时自己进入条件等待队列,用一个变量记录自己持有锁的次数(saveState)
//然后释放锁的时候唤醒同步队列的第一个阻塞线程,即B,B醒了以后,尝试获取锁
//假设只有这两个线程,则B获取锁成功,number++,然后signal(),将A加入到同步队列,然后await(),
//释放锁,唤醒A,将自己阻塞。
//A醒来后,判断自己是否在同步队列中,在的话跳出自旋(这个地方肯定是在同步队列中的,因为唤醒只会唤醒
//同步队列上的线程。此处while循环是怕线程在别的情况下醒来)
//继续执行await()方法,没执行完,在await()方法内部阻塞了
//然后调用acquire(node,saveState)尝试获得锁,A获取成功,然后number++,在signal(),再调用await()
//这样A和B可以一直输出到100
//但是缺少了unlock()操作,ReentrantLock被A和B分别重入50次,A和B可以相互交替运行完全是因为await()和
//signal()的机制,所以未改正前,当A退出时,锁被A持有,且state = 50,表示重入了50次。
//调用了signal()也只是把B线程从条件队列移动到同步队列,没有调用await(),没让出锁。
//即便在最后调用一次unlock(),也只是将state - 1,变为49,依然未释放锁。
//所以,在每次lock()之后一定要unlock().
//改正
class Task2 implements Runnable{
private int number = 0;
private ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
@Override
public void run(){
//1,2 3 4,5 6 7,8 9 在2,5,8await,在3,6,9signal
while(number<100){
lock.lock();
number++;
System.out.println(Thread.currentThread().getName()+number);
condition.signal();
try{
if(number<100)
condition.await();
}catch (InterruptedException e) {
e.printStackTrace();
}finally{
lock.unlock();
}
}
}
}