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();
}
}
}