Java Concurrency - Lock Interface
Eine java.util.concurrent.locks.Lock-Schnittstelle wird als Thread-Synchronisationsmechanismus verwendet, der synchronisierten Blöcken ähnelt. Der neue Verriegelungsmechanismus ist flexibler und bietet mehr Optionen als ein synchronisierter Block. Die Hauptunterschiede zwischen einer Sperre und einem synchronisierten Block sind folgende:
Guarantee of sequence- Der synchronisierte Block bietet keine Garantie für die Reihenfolge, in der der wartende Thread Zugriff erhält. Lock-Schnittstelle behandelt es.
No timeout- Der synchronisierte Block hat keine Zeitüberschreitungsoption, wenn keine Sperre gewährt wird. Die Sperrschnittstelle bietet eine solche Option.
Single method - Der synchronisierte Block muss vollständig in einer einzelnen Methode enthalten sein, während die Methoden lock () und refresh () einer Sperrschnittstelle in verschiedenen Methoden aufgerufen werden können.
Sperrmethoden
Im Folgenden finden Sie eine Liste wichtiger Methoden, die in der Lock-Klasse verfügbar sind.
Sr.Nr. | Methode & Beschreibung |
---|---|
1 | public void lock() Erwirbt das Schloss. |
2 | public void lockInterruptibly() Erhält die Sperre, sofern der aktuelle Thread nicht unterbrochen wird. |
3 | public Condition newCondition() Gibt eine neue Bedingungsinstanz zurück, die an diese Sperrinstanz gebunden ist. |
4 | public boolean tryLock() Erwirbt die Sperre nur, wenn sie zum Zeitpunkt des Aufrufs frei ist. |
5 | public boolean tryLock() Erwirbt die Sperre nur, wenn sie zum Zeitpunkt des Aufrufs frei ist. |
6 | public boolean tryLock(long time, TimeUnit unit) Erhält die Sperre, wenn sie innerhalb der angegebenen Wartezeit frei ist und der aktuelle Thread nicht unterbrochen wurde. |
7 | public void unlock() Löst die Sperre auf. |
Beispiel
Das folgende TestThread-Programm demonstriert einige dieser Methoden der Lock-Schnittstelle. Hier haben wir lock () verwendet, um die Sperre zu erhalten, und lock (), um die Sperre aufzuheben.
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class PrintDemo {
private final Lock queueLock = new ReentrantLock();
public void print() {
queueLock.lock();
try {
Long duration = (long) (Math.random() * 10000);
System.out.println(Thread.currentThread().getName()
+ " Time Taken " + (duration / 1000) + " seconds.");
Thread.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.printf(
"%s printed the document successfully.\n", Thread.currentThread().getName());
queueLock.unlock();
}
}
}
class ThreadDemo extends Thread {
PrintDemo printDemo;
ThreadDemo(String name, PrintDemo printDemo) {
super(name);
this.printDemo = printDemo;
}
@Override
public void run() {
System.out.printf(
"%s starts printing a document\n", Thread.currentThread().getName());
printDemo.print();
}
}
public class TestThread {
public static void main(String args[]) {
PrintDemo PD = new PrintDemo();
ThreadDemo t1 = new ThreadDemo("Thread - 1 ", PD);
ThreadDemo t2 = new ThreadDemo("Thread - 2 ", PD);
ThreadDemo t3 = new ThreadDemo("Thread - 3 ", PD);
ThreadDemo t4 = new ThreadDemo("Thread - 4 ", PD);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
Dies führt zu folgendem Ergebnis.
Ausgabe
Thread - 1 starts printing a document
Thread - 4 starts printing a document
Thread - 3 starts printing a document
Thread - 2 starts printing a document
Thread - 1 Time Taken 4 seconds.
Thread - 1 printed the document successfully.
Thread - 4 Time Taken 3 seconds.
Thread - 4 printed the document successfully.
Thread - 3 Time Taken 5 seconds.
Thread - 3 printed the document successfully.
Thread - 2 Time Taken 4 seconds.
Thread - 2 printed the document successfully.
Wir haben hier die ReentrantLock-Klasse als Implementierung der Lock-Schnittstelle verwendet. Mit der ReentrantLock-Klasse kann ein Thread eine Methode sperren, auch wenn bereits eine andere Methode gesperrt ist.