多窗口卖票:
三个窗口卖票,一共n中张票要求三个窗口同时卖,互不干扰。知道n张票卖完为止。
1.使用同步代码块解决实现Runnable接口的类的线程安全的问题
代码:
public class Thread_Exercise_Sticket {
public static void main(String[] args) {
Tickets tickets1 = new Tickets(); //创建实现Runable接口类的实例对象
//通过实现接口,我们只需要一个对象就可以实现多个对象的效果
Thread thread1 = new Thread(tickets1);//通过 new Runable(对象) 的方式调用Thread中的方法
Thread thread2 = new Thread(tickets1);
Thread thread3 = new Thread(tickets1);
thread1.setName("窗口1");
thread2.setName("窗口2");
thread3.setName("窗口3");
thread1.start();
thread2.start();
thread3.start();
}
}
class Tickets implements Runnable{ //创建一个实现Runable接口的类
public static int ticket = 10; //通过实现接口,我们只需要一个对象就可以实现多个对象的效果
Object obj = new Object();
@Override
public void run() { // 实现runable中的run()方法
while (true) {
//可以使用this代替obj是因为我们只创建了一个Tickets类的对象
synchronized (this) { //同步代码块
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + " 售出 " + ticket + "号 票");
ticket--;
} else {
break;
}
}
}
}
}
结果:
2.如果操作共享数据的代码声明在一个方法中,那么我们就可以将此方法声明为同步的
代码:
public class Thread_Exercise2_Sticket {
public static void main(String[] args) {
Tickets2 tickets2 = new Tickets2(); //创建实现Runable接口类的实例对象
//通过实现接口,我们只需要一个对象就可以实现多个对象的效果
Thread thread1 = new Thread(tickets2);//通过 new Runable(对象) 的方式调用Thread中的方法
Thread thread2 = new Thread(tickets2);
Thread thread3 = new Thread(tickets2);
thread1.setName("窗口1");
thread2.setName("窗口2");
thread3.setName("窗口3");
thread1.start();
thread2.start();
thread3.start();
}
}
class Tickets2 implements Runnable{ //创建一个实现Runable接口的类
public static int ticket = 10; //通过实现接口,我们只需要一个对象就可以实现多个对象的效果
Object obj = new Object(); //必须写在run()外面
@Override
public void run() { // 实现runable中的run()方法
while (true) {
method(); //调用同步方法
if(ticket==0)
break;
}
}
private synchronized void method() { //同步方法
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + " 售出 " + ticket + "号 票");
ticket--;
}
}
}
结果:
3.通过使用Lock(锁),解决线程的安全问题
代码:
public class Thread_Exercise3_threadSafe {
public static void main(String[] args) {
Tickets3 tickets3 = new Tickets3(); //创建实现Runable接口类的实例对象
//通过实现接口,我们只需要一个对象就可以实现多个对象的效果
Thread thread1 = new Thread(tickets3);//通过 new Runable(对象) 的方式调用Thread中的方法
Thread thread2 = new Thread(tickets3);
Thread thread3 = new Thread(tickets3);
thread1.setName("窗口1");
thread2.setName("窗口2");
thread3.setName("窗口3");
thread1.start();
thread2.start();
thread3.start();
}
}
class Tickets3 implements Runnable{ //创建一个实现Runable接口的类
public static int ticket = 10; //通过实现接口,我们只需要一个对象就可以实现多个对象的效果
private static ReentrantLock lock = new ReentrantLock();
@Override
public void run() { // 实现runable中的run()方法
while (true) {
try {
lock.lock(); //调用lock(),保证线程安全
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + " 售出 " + ticket + "号 票");
ticket--;
} else {
break;
}
} finally {
lock.unlock();//解锁
}
}
}
}
结果: