还是那个3个窗口卖100张票的问题,这次我们使用ReentrantLock类来帮助我们解决问题。
卖票程序:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ticketSell implements Runnable {
Lock lock=new ReentrantLock();
static int num = 1000;
static Object obj = new Object();
@Override
public void run() {
lock.lock();
try {
while (num > 0) {
System.out.println(Thread.currentThread().getName() + ": 还剩" + num-- + "张票");
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}finally {
lock.unlock();
}
}
}
主函数:
public class test {
public static void main(String[] args) {
ticketSell ts=new ticketSell();
Thread ck1 = new Thread(ts, "窗口1");
Thread ck2 = new Thread(ts, "窗口2");
Thread ck3 = new Thread(ts, "窗口3");
ck1.start();
ck2.start();
ck3.start();
}
}
程序分析:
我们使用三个类运行一个实例,因为是一个实例,所以操作的是同一把锁。一般多线程都是跑一个实例,及时跑一个实例每个线程都会准备实例副本。
注意: Lock lock=new ReentrantLock();语句如果写到run方法里,那么就会运行出错,因为那样每一个线程都会创建不同的锁,这不是我们想要的,因为我们需要让不同的线程操作同一把锁。
程序改进:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ticketSell implements Runnable {
static Lock lock=new ReentrantLock();
static int num = 1000;
static Object obj = new Object();
@Override
public void run() {
try {
while (num > 0) {
lock.lock();
System.out.println(Thread.currentThread().getName() + ": 还剩" + num-- + "张票");
lock.unlock();
Thread.yield();
}
}catch (Exception e){}
}
}
主函数:
public class test {
public static void main(String[] args) {
ticketSell ts = new ticketSell();
Thread ck1 = new Thread(ts, "窗口1");
Thread ck2 = new Thread(ts, "窗口2");
Thread ck3 = new Thread(ts, "窗口3");
ck1.start();
ck2.start();
ck3.start();
}
}
运行结果:
窗口2: 还剩1000张票
窗口2: 还剩999张票
窗口2: 还剩998张票
窗口2: 还剩997张票
窗口2: 还剩996张票
窗口3: 还剩995张票
窗口2: 还剩994张票
窗口3: 还剩993张票
窗口2: 还剩992张票
窗口3: 还剩991张票
窗口2: 还剩990张票
窗口3: 还剩989张票
窗口2: 还剩988张票
窗口3: 还剩987张票
窗口2: 还剩986张票
窗口3: 还剩985张票
窗口2: 还剩984张票
窗口2: 还剩983张票
窗口2: 还剩982张票
窗口2: 还剩981张票
···
这样做让每个线程做减数后yeild让出本次时间片,这样就不会出现一个线程抢到锁后一直都是这个线程在跑的情况。