Java小題目之兩個執行緒順序列印A、B
阿新 • • 發佈:2019-01-24
1、問題描述
使用Java多執行緒方式來實現迴圈列印A、B,並保證不亂序。
2、解決方案
java在編寫多執行緒程式時,為了保證執行緒安全,需要對資料同步,經常用到兩種同步方式就是Synchronized和重入鎖ReentrantLock。
- 利用synchronized關鍵字來實現
package org.ibenben.test;
public class OrderThreadTest {
public static void main(String[] args){
OrderThreadTest test = new OrderThreadTest();
Object lock = new Object();
test.new Output(lock, "A").start();
test.new Output(lock, "B").start();
}
class Output extends Thread{
private Object lock;
private String value;
public Output(Object lock,String value) {
this.lock = lock;
this .value = value;
}
@Override
public void run() {
synchronized (lock) {
while (true) {
try {
System.out.println(value);
lock.notifyAll();
lock .wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
2.使用ReentrantLock來實現
package org.ibenben.test;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class OrderThreadTest {
private ReentrantLock lock = new ReentrantLock();
Condition aCondition = lock.newCondition();
Condition bCondition = lock.newCondition();
public static void main(String[] args){
OrderThreadTest test = new OrderThreadTest();
test.new AOutput().start();
test.new BOutput().start();
}
class AOutput extends Thread{
@Override
public void run() {
while (true) {
try {
lock.lock();
System.out.println("A");
bCondition.signal();
aCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}
class BOutput extends Thread{
@Override
public void run() {
while (true) {
try {
lock.lock();
System.out.println("B");
aCondition.signal();
bCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}
}
3、Synchronized與ReentrantLock
ReentrantLock與synchronized關鍵字一樣,屬於互斥鎖,synchronized中的鎖是非公平的(公平鎖是指多個執行緒等待同一個鎖時,必須按照申請鎖的時間順序來依次獲得鎖),ReentrantLock預設情況下也是非公平的,但可以通過帶布林值的建構函式要求使用公平鎖。執行緒通過ReentrantLock的lock()方法獲得鎖,用unlock()方法釋放鎖。
ReentrantLock和synchronized關鍵字的區別
- ReentrantLock在等待鎖時可以使用lockInterruptibly()方法選擇中斷, 改為處理其他事情,而synchronized關鍵字,執行緒需要一直等待下去。同樣的,tryLock()方法可以設定超時時間,用於在超時時間內一直獲取不到鎖時進行中斷。
- ReentrantLock可以實現公平鎖,而synchronized的鎖是非公平的。
- ReentrantLock擁有方便的方法用於獲取正在等待鎖的執行緒。
- ReentrantLock可以同時繫結多個Condition物件,而synchronized中,鎖物件的wait()和notify()或notifyAll()方法可以實現一個隱含的條件,如果要和多於一個條件關聯時,只能再加一個額外的鎖,而ReentrantLock只需要多次呼叫newCondition方法即可。
效能比較
在JDK1.6之前,ReentrantLock的效能要明顯優於synchronized,但是JDK1.6中加入了很多針對鎖的優化措施,synchronized和ReentrantLock的效能基本完全持平了。
ReentrantLock缺點
ReentrantLock的主要缺點是方法需要置於try-finally塊中,另外,開發人員需要負責獲取和釋放鎖,而開發人員常常忘記在finally中釋放鎖。