Java重入鎖、Condition、信息量
1.重入鎖
import java.util.concurrent.locks.ReentrantLock;
/**
* 重入鎖
* @author wsz
* @date 2017年12月2日
*/
public class ReentertLock implements Runnable{
public static ReentrantLock lock = new ReentrantLock();//重入鎖
public static long count =0L;
public static void main(String[] args) throws InterruptedException {
ReentertLock reentertLock = new ReentertLock();
Thread t1 = new Thread(reentertLock);//接口構造函數
Thread t2 = new Thread(reentertLock);
t1.start();t2.start();
t1.join();t2.join();
System.out.println(count);
}
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
lock.lock();//加鎖
count++;
lock.unlock();//解鎖,次數必須與加鎖次數一致,否則將導致
}
}
}
2.重入鎖中斷請求
import java.util.concurrent.locks.ReentrantLock;
/**
* 重入鎖之中斷鎖請求
* 1.提供死鎖環境
* 2.結束死鎖
* 3.被中斷線程無法完成任務
* @author wsz
* @date 2017年12月2日
*/
public class IntLock implements Runnable{
public static ReentrantLock lock1 = new ReentrantLock();//重入鎖
public static ReentrantLock lock2 = new ReentrantLock();//重入鎖
//控制加鎖順序,用於創造死鎖
private int lock;
public IntLock(int lock) {
super();
this.lock = lock;
}
public static void main(String[] args) throws InterruptedException {
IntLock intLock1 = new IntLock(1);
IntLock intLock2 = new IntLock(2);
Thread t1 = new Thread(intLock1);//t1先佔有鎖lock1,再請求lock2
Thread t2 = new Thread(intLock2);//t2先佔有lock2,再請求lock1
t1.start();t2.start();//開啓後形成死鎖
Thread.sleep(2000);
t2.interrupt();//中斷t2,t1將執行結束,t2放棄並結束
}
@Override
public void run() {
try {
if(lock == 1) {
lock1.lockInterruptibly();//在等待鎖時可以響應中斷
try {
Thread.sleep(1000);
}catch (InterruptedException e) {}
lock2.lockInterruptibly();//在等待鎖時可以響應中斷
}else {
lock2.lockInterruptibly();//在等待鎖時可以響應中斷
try {
Thread.sleep(1000);
}catch (InterruptedException e) {}
lock1.lockInterruptibly();//在等待鎖時可以響應中斷
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
if(lock1.isHeldByCurrentThread()) {//Queries if this lock is held by the current thread.
lock1.unlock();
}
if(lock2.isHeldByCurrentThread()) {//判斷當前線程是否擁有該鎖
lock2.unlock();
}
System.out.println(Thread.currentThread().getId()+"線程退出");
}
}
}
3.Condition條件
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* 重入鎖與Condition
* @author wsz
* @date 2017年12月2日
*/
public class ConditionLock implements Runnable{
public static ReentrantLock lock = new ReentrantLock();//重入鎖
public static Condition condition = lock.newCondition();//綁定相關的Condition實例
@Override
public void run() {
try {
lock.lock();
condition.await();//等待並釋放鎖
System.out.println("aaa");
}catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
ConditionLock cl = new ConditionLock();
Thread t1 = new Thread(cl);
t1.start();
Thread.sleep(2000);
lock.lock();
condition.signal();//喚醒等待在Condition上的線程
lock.unlock();//解鎖之後,將打印,否則無法執行。
}
}
4.信號量Semaphore
信號量提供多個線程來同時訪問某一個資源。內部鎖synchronized和重入鎖ReentrantLock一次都只允許一個線程訪問一個資源。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* 信號量
* @author wsz
* @date 2017年12月2日
*/
public class SemaphoreTest implements Runnable{
//型號量准入數、是否公平鎖;設置爲3將以每3個線程一組打印信息
final Semaphore semp = new Semaphore(3, false);
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(20);//開啓保護20個線程的線程池
SemaphoreTest demo = new SemaphoreTest();
for(int i=0 ;i <50 ;i++) {
exec.submit(demo);
}
}
@Override
public void run() {
try {
semp.acquire(); //嘗試獲得一個准入的許可,如無法獲得將等待,直到獲得一個許可或者當前線程被中斷
Thread.sleep(2000);//模擬耗時
System.out.println(Thread.currentThread().getId()+":ok ok");
semp.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}