本篇将着手线程并发库,即java.util.concurrent包中的几个重要类。线程并发库是jdk1.5引入的,并发库的引入使得多线程开发更加的灵活多变,除此之外,因为java是面向对象的语言,线程并发库的引入让java多线程编程更加正统。本文主要内容如下:
Lock接口是线程并发库中锁对象的父接口,本文将通过他的实现类ReentrantLock来说明,ReentrantLock是一个可重入的互斥锁,也被称之为“独占锁”,顾名思义,ReentrantLock在同一时刻只能被一个线程拥有,reentrant英文释义就是可重入的,意义就是它可以被单个线程多次获取,相当于synchronized关键字的作用,只不过ReentrantLock是基于对象的。
Condition的作用是对锁进行更加精确的控制,Condition中的await()/signal()/signalAll和Object中wait()/notify()/notifyAll()方法有异曲同工之妙,不同的是Object中的三个方法是基于synchronized关键字,而Condition中的三个方法则需要和Lock联合使用。针对一个Lock对象可以有多个Condition对象,这就是Condition对象更加灵活的原因。
仓库模型代码:
package com.tml.javaCore.concurrent.lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
*
* 多线程 生产者-消费者仓库模型
*
* @author Administrator
*
*/
public class Repository {
/*
* 仓库的容量
*/
private int capacity;
/*
* 仓库的实际容量
*/
private int size;
/*
* 独占锁对象,相当于synchronized
*/
private Lock lock;
/*
* 仓库满时的条件
*/
private Condition fullCondition;
/*
* 仓库空时的条件
*/
private Condition emptyCondition;
public Repository(int capacity) {
this.capacity = capacity;
this.size = 0;
lock = new ReentrantLock();
fullCondition = lock.newCondition();
emptyCondition = lock.newCondition();
}
/**
*
* 生产者生产资源
*
* @param produceAmount
* 生产者预生产量
*/
public void produce(int produceAmount) {
//上锁
lock.lock();
try {
while (produceAmount > 0) {
while (size >= capacity) {
System.out.println("has fulled!");
//仓库已经满了,相当于wait()操作,只有当fullCondition.signalAll()才能继续执行
fullCondition.await();
}
/*
* 获取实际的生产量
*/
int actAmount = (size + produceAmount) > capacity ? capacity - size : produceAmount;
size += actAmount;
System.out.println(
Thread.currentThread().getName() + ":has + :" + actAmount + ",the actual size is:" + size);
produceAmount -= actAmount;
// 通知消费者来消费,相当于notifyAll()操作
emptyCondition.signalAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//释放锁一般放在finally中
lock.unlock();
}
}
/**
*
* 消费者消费资源
*
* @param consumeAmount
* 消费者预消费量
*/
public void consume(int consumeAmount) {
lock.lock();
try {
while (consumeAmount > 0) {
while (size <= 0) {
System.out.println("empty!");
emptyCondition.await();
}
/*
* 获取实际的消费量
*/
int actAmount = (size < consumeAmount) ? size : consumeAmount;
size -= actAmount;
System.out.println(
Thread.currentThread().getName() + ":has - :" + actAmount + ",the actual size is:" + size);
consumeAmount -= actAmount;
// 通知生产者来生产
fullCondition.signalAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
@Override
public String toString() {
return "Repository [capacity=" + capacity + ", size=" + size + "]";
}
}
测试类代码:
package com.tml.javaCore.concurrent.lock;
/**
* 生产者-消费者
* @author Administrator
*
*/
public class TestDemo {
public static void main(String[] args) {
//新建一个容量为100的仓库
Repository repository =new Repository(100);
//模拟生产者,每隔1000毫秒生产23个产品
new Thread(new Runnable() {
public void run() {
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
repository.produce(23);
}
}
},"producer1").start();
//模拟消费者1,每隔2500毫秒消费产品25
new Thread(new Runnable() {
public void run() {
while(true){
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
repository.consume(25);
}
}
},"consumer1").start();
//模拟消费者2,每隔1500毫秒消费产品10
new Thread(new Runnable() {
public void run() {
while(true){
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
repository.consume(10);
}
}
},"consumer2").start();
}
}
下面是某一次的部分结果输出:
producer1:has + :23,the actual size is:23
consumer2:has - :10,the actual size is:13
producer1:has + :23,the actual size is:36
consumer1:has - :25,the actual size is:11
producer1:has + :23,the actual size is:34
consumer2:has - :10,the actual size is:24
producer1:has + :23,the actual size is:47
consumer2:has - :10,the actual size is:37
consumer1:has - :25,the actual size is:12
producer1:has + :23,the actual size is:35
producer1:has + :23,the actual size is:58
consumer2:has - :10,the actual size is:48
producer1:has + :23,the actual size is:71
consumer1:has - :25,the actual size is:46
consumer2:has - :10,the actual size is:36
producer1:has + :23,the actual size is:59
producer1:has + :23,the actual size is:82
consumer2:has - :10,the actual size is:72
consumer1:has - :25,the actual size is:47
producer1:has + :23,the actual size is:70
consumer2:has - :10,the actual size is:60
producer1:has + :23,the actual size is:83
producer1:has + :17,the actual size is:100
has fulled!
consumer2:has - :10,the actual size is:90
producer1:has + :6,the actual size is:96
consumer1:has - :25,the actual size is:71
producer1:has + :23,the actual size is:94
consumer2:has - :10,the actual size is:84
producer1:has + :16,the actual size is:100
has fulled!
consumer1:has - :25,the actual size is:75