这个东西,到底是做什么用的呢?上过操作系统课程的童鞋们,一定听过的,生产者和消费者问题

我首先不用这个玩意做一下,简单的生产消费。

消费者,从工厂拿一个东西,出来。运行在线程中的。

/**
*
* @author JetWang
*
*/
public class Customer {
/**
* 依赖工厂
*/
public Factory facrory;
public Customer(Factory facrory) {

this.facrory = facrory;
}
public void consum(final int value){
new Thread(){
@Override
public void run() {
// TODO Auto-generated method stub
facrory.get(value);
}
}.start();
}
}

生产者类似

public class Produce {
/**
* 依赖工厂
*/
public Factory facrory;
public Produce(Factory facrory) {
this.facrory = facrory;
};
public void produce(final int value){
new Thread(){
@Override
public void run() {
// TODO Auto-generated method stub
facrory.put(value);
}
}.start();
}
}

我们的工厂,使用Lock,保护资源共享,修改我们的实例变量的count属性,通过lock控制,线程并发操作。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 仓库类
* @author JetWang
*
*/
public class Factory {
private int count;//仓库的大小
private Lock lock;
public Factory() {
lock=new ReentrantLock();//可重入锁
this.count=0; // TODO Auto-generated constructor stub
}
/**
* 商品入库
*/
public void put(int value){
try {
lock.lock();
count+=value;
System.out.println(Thread.currentThread().getName() + " put " + value +" ----> the count: " + count);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
lock.unlock();
}
}
public void get(int value){
try {
lock.lock();
count-=value;
System.out.println(Thread.currentThread().getName() + " get " + value +" ----> the count: " + count);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
lock.unlock();
}
}

}

下面这个是我们的测试类:

public class Test {

public static void main(String[] args) {
// TODO Auto-generated method stub
Factory factory=new Factory();//公有的工厂
Produce pro=new Produce(factory);
Customer cus=new Customer(factory);
pro.produce(10);
cus.consum(5);
pro.produce(20);
cus.consum(5);
pro.produce(5);
cus.consum(35);
}

}

Thread-0 put 10 —-> the count: 10

Thread-1 get 5 —-> the count: 5

Thread-4 put 5 —-> the count: 10

Thread-5 get 35 —-> the count: -25

Thread-2 put 20 —-> the count: -5

Thread-3 get 5 —-> the count: -10

看哈我们的结果,最后的结果却是是没得错误,很好的完成了工作,是不是呢?但是仓库怎么可能为负数的呢?没有很好的控制吧!消费者在消费的时候我们不可能仓库没得东西都可以拿走吧!这个不符合逻辑

这个就是Condition (条件使用的时候啦,信号)

Condition的作用是对锁进行更精确的控制。Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signalAll()相当于Object的notifyAll()方法。不同的是,Object中的wait(),notify(),notifyAll()方法是和”同步锁”(synchronized关键字)捆绑使用的;而Condition是需要与”互斥锁”/”共享锁”捆绑使用的。

条件(也称为条件队列 或条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为 true 的另一个线程通知它之前,一直挂起该线程(即让其“等待”)。因为访问此共享状态信息发生在不同的线程中,所以它必须受保护,因此要将某种形式的锁与该条件相关联。等待提供一个条件的主要属性是:以原子方式 释放相关的锁,并挂起当前线程,就像 Object.wait 做的那样。

Condition 实例实质上被绑定到一个锁上。要为特定 Lock 实例获得 Condition 实例,请使用其newCondition() 方法

下面为我们改进的工厂类

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Factory2 {
private int count;//仓库的大小
private Lock lock;
private Condition fullCondiction;//满的信号
private Condition emptyCondiction;//空的信号
private int capity;


public Factory2() {
lock=new ReentrantLock();
this.count=0;
this.capity=15;
fullCondiction=lock.newCondition();
emptyCondiction=lock.newCondition();
}
public void get(int value){
lock.lock();
try {
int left=value;
while(left>0){
while(count<=0){
emptyCondiction.await();
}
int dec=count<left?count:left;
count-=dec;
left-=dec;
System.out.println(Thread.currentThread().getName()
+ "----要消费的数量:" + value +";"
+ ";实际消费的数量: " + dec + ";"
+ ";仓库现存数量:" + count
+ ";;有多少件商品没有消费:" + left);
//没有满的信号
fullCondiction.signal();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
lock.unlock();
}

}
public void put(int value){
lock.lock();
try {
int left=value;
while(count>=capity){
fullCondiction.await();
}
int in=this.count+left>this.capity?this.capity-count:left;
count+=in;
left-=in;
System.out.println(Thread.currentThread().getName()
+ "----要入库数量: " + value
+";;实际入库数量:" + in
+ ";;仓库货物数量:" + count
+ ";;没有入库数量:" + left);
//仓库有东西,通知消费
emptyCondiction.signal();

} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
lock.unlock();
}
}
}

Test

public class Test {

public static void main(String[] args) {
// TODO Auto-generated method stub
Factory2 factory=new Factory2();//公有的工厂
Produce pro=new Produce(factory);
Customer cus=new Customer(factory);
pro.produce(10);
cus.consum(5);
pro.produce(20);
cus.consum(5);
pro.produce(5);
cus.consum(35);
}

}

结果:

Thread-0—-要入库数量: 10;;实际入库数量:10;;仓库货物数量:10;;没有入库数量:0

Thread-1—-要消费的数量:5;;实际消费的数量: 5;;仓库现存数量:5;;有多少件商品没有消费:0

Thread-3—-要消费的数量:5;;实际消费的数量: 5;;仓库现存数量:0;;有多少件商品没有消费:0

Thread-4—-要入库数量: 5;;实际入库数量:5;;仓库货物数量:5;;没有入库数量:0

Thread-2—-要入库数量: 20;;实际入库数量:10;;仓库货物数量:15;;没有入库数量:10

Thread-5—-要消费的数量:35;;实际消费的数量: 15;;仓库现存数量:0;;有多少件商品没有消费:20

没有错误哦~

在Condition中,用await()替换wait(),用signal()替换 notify(),用signalAll()替换notifyAll(),对于我们以前使用传统的Object方法,Condition都能够给予实现。 在线程之间进行同步~