我们已经了解了线程同步的基本概念以及使用synchronized关键字的各种机制。Java提供了另一种基于锁接口和实现它的类(如ReNANTTROLK)同步代码块的机制。在本教程中,我们将看到锁接口的基本用法,以解决打印机队列问题。
![b3a79183b8c4276e1ff3467eab1d8d58.png](https://img-blog.csdnimg.cn/img_convert/b3a79183b8c4276e1ff3467eab1d8d58.png)
Lock Interface
java.util.concurrent.locks.lock是一种线程同步机制,与同步块类似。然而,使用lock比同步块更灵活、更复杂。由于lock是一个接口,所以需要使用它的一个实现来在应用程序中使用lock。ReentrantLock是锁接口的一种实现。
下面是锁接口的简单用法。
Lock lock = new ReentrantLock();
lock.lock();
//critical section
lock.unlock();
上面首先创建一个锁的实例。然后调用它的lock()方法。现在实例被锁定。调用lock()的任何其他线程将被阻塞,直到锁定该锁的线程调用unlock()。
最后调用unlock(),lock现在被解锁,以便其他线程可以锁定它。
Lock Interface和synchronized关键字之间的区别
Lock和synchronized块之间的主要区别是:
1)尝试访问同步块时发生超时是不可能的。 使用Lock.tryLock(长超时,TimeUnit timeUnit),这是可能的。
2)synchronized必须完全包含在单个方法中。 Lock可以在单独的方法中调用lock()和unlock()。
使用lock模拟打印机队列
在本例中,程序将模拟打印机的行为。您可以在不同的时间间隔或同时向打印机提交多个打印作业。打印机将从打印机队列中获取一个作业并打印它。其余的工作将在那里等待。一旦打印机完成手头的打印作业,它将从队列中选择另一个作业并开始打印。然后再循环。
PrintingJob.java
此类表示可以提交给打印机的打印工作。这个类实现了可运行的接口,这样打印机可以在轮到它时执行它。
class PrintingJob implements Runnable
{
private PrinterQueue printerQueue;
public PrintingJob(PrinterQueue printerQueue)
{
this.printerQueue = printerQueue;
}
@Override
public void run()
{
System.out.printf("%s: Going to print a document