Java实现多线程买票同步示例

版权申诉
5星 · 超过95%的资源 1 下载量 48 浏览量 更新于2024-08-08 收藏 90KB DOCX 举报
"Java模拟多线程买票问题是一个经典的并发编程示例,旨在演示如何在多线程环境中控制共享资源的访问。该问题的核心在于使用`synchronized`关键字和锁机制来实现线程同步,确保在多窗口售票时不会出现票数超卖的情况。本文档将介绍两种不同的实现方法来解决这个问题。" 在Java中,多线程买票问题通常通过以下两个关键概念来解决: 1. synchronized:这是一个关键字,用于实现线程同步。当多个线程试图访问共享资源时,synchronized可以确保同一时间只有一个线程能够执行特定的代码块,从而避免数据不一致。 2. 锁:锁是另一种同步机制,它可以更细粒度地控制对共享资源的访问。在Java中,除了内置的`synchronized`锁,还可以使用`java.util.concurrent`包中的Lock接口(如ReentrantLock)来显式地声明和管理锁。 ### 方式1:使用synchronized关键字 在方式1中,`SaleTicket`类实现了`Runnable`接口,并在`run`方法中使用`synchronized`关键字对代码块进行同步。这里的`this`作为锁的对象,意味着每个线程在进入`run`方法时都需要获取当前`SaleTicket`实例的锁。这种方式虽然简单,但并没有明确地使用对象锁,可能导致线程安全问题。 ```java public class SaleTicket implements Runnable { public int total; public int count; public SaleTicket() { total = 100; count = 0; } public void run() { while (total > 0) { synchronized (this) { if (total > 0) { try { Thread.sleep(new Random().nextInt(1000)); } catch (Exception e) { e.printStackTrace(); } count++; total--; System.out.println(Thread.currentThread().getName() + "\t当前票号:" + count); } } } } public static void main(String[] args) { SaleTicket st = new SaleTicket(); for (int i = 0; i <= 5; i++) { new Thread(st, "售票点" + i).start(); } } } ``` ### 方式2:使用显式锁(Lock) 在方式2中,`SaleTicketThread`类继承自`Thread`,并使用了一个私有对象`obj`作为锁。这里使用`synchronized`关键字配合显式锁对象`obj`来控制同步。相比于方式1,这种方式更加灵活,可以单独获取锁和释放锁,但同时也需要更多的代码来管理。 ```java public class SaleTicketThread extends Thread { public static int tickets = 100; private Object obj = new Object(); @Override public void run() { while (true) { synchronized (obj) { if (tickets > 0) { // ...其他操作 } } } } } ``` 在这两种方式中,线程会随机睡眠一段时间以模拟售票窗口的处理速度差异,然后更新票数和打印当前票号。通过这种方式,可以观察到线程同步的效果,确保票数的正确减少,避免出现负数或超卖的情况。 在实际开发中,应根据项目需求和性能考虑选择合适的方法。例如,如果需要更复杂的同步策略,可能需要使用`Lock`接口提供的高级特性,如公平锁、可中断锁等。而简单的同步需求,使用`synchronized`关键字可能更为简洁。理解和熟练掌握这些并发编程工具对于编写高效、安全的多线程Java程序至关重要。