线程的同步与协作,这个概念很普通就是说,一个线程需要等另一个线程完成或者完成某部分时才能继续工作。
线程之间的同步与协作,有一个经典的场景:生产者与消费者。如库存不足,那么消费者线程需要等待,生产者生产出足够的物品。生产者和消费者都需要访问物品库,同一时刻(在某个操作下)只能有一个线程占用。 既然是线程,那么线程运行CPU时间片不怎么好控制,涉及到数据安全还需要涉及到锁。临界资源只能有一个线程占用,那么等待的线程需要释放锁,但又要保留线程当前的运算结果中间值。使用wait方法,释放线程占用的资源,进入阻塞状态,等待生产者线程唤醒,然后重新去抢占锁等其他资源就使用条件(Condition)便于线程间通信,来实现
因为缺钱,就拿取钱作为例子。
这是账户代码,取钱和存钱
package com.Thread.sync;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Accout {
private Lock lock = new ReentrantLock(true);
private Condition newDeposit = lock.newCondition(); // 创建一个条件
private int money=100;
public void addMoney(int aum){
lock.lock();
try {
Thread.sleep(1000);
money=money+aum;
newDeposit.signalAll();
System.out.println(" 存 "+aum+" 元 现在余额共:"+money);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
lock.unlock();
}
}
/**
*取款是一定要成功的,不成功便等待
* @param put
*/
public void putMoney(int put){
lock.lock();
try {
Thread.sleep(1000);
//代表历史处理过的逻辑,
System.out.println("取钱之前的准备工作。。。。");
while(money<put){
System.out.println("取出 "+put+" 元" +" 余额不足无法取出 当前余额:"+money);
newDeposit.await();
}
Thread.sleep(1000);
money=money-put;
System.out.println("成功取出"+put+" 元 ,余额:"+money+" 元-------------");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
lock.unlock();
}
}
}
View Code
取钱线程
package com.Thread;
import java.util.Random;
import com.Thread.sync.Accout;
public class GetMoney implements Runnable{
private Accout accout;
public GetMoney(Accout accout){
this.accout=accout;
}
@Override
public void run() {
// TODO Auto-generated method stub
int n=10;
accout.putMoney(new Random().nextInt(8000)+2000);
}
}
View Code
存钱线程
package com.Thread.sync;
import java.util.Random;
public class AddMoney implements Runnable{
private Accout accout;
public AddMoney(Accout accout) {
// TODO Auto-generated constructor stub
this.accout=accout;
}
@Override
public void run() {
int n=20;
while(n>1){
accout.addMoney(new Random().nextInt(2000));
n--;
}
}
}
View Code
测试类
package com.Thread.sync;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.Thread.GetMoney;
public class Sync {
public static void main(String[] args) {
// TODO Auto-generated method stub
Accout accout=new Accout();
ExecutorService executor = Executors.newCachedThreadPool();
executor.execute(new AddMoney(accout));
executor.execute(new GetMoney(accout));
}
}
View Code
运行结果:
存 587 元 现在余额共:687
取钱之前的准备工作。。。。//证明线程之前的运算被保存,并没有重复运行
取出 2386 元 余额不足无法取出 当前余额:687
存 221 元 现在余额共:908
取出 2386 元 余额不足无法取出 当前余额:908
存 5 元 现在余额共:913
取出 2386 元 余额不足无法取出 当前余额:913
存 1079 元 现在余额共:1992
取出 2386 元 余额不足无法取出 当前余额:1992
存 1145 元 现在余额共:3137
成功取出2386 元 ,余额:751 元-------------
存 197 元 现在余额共:948
存 1029 元 现在余额共:1977
存 1104 元 现在余额共:3081
存 1542 元 现在余额共:4623
存 650 元 现在余额共:5273
存 585 元 现在余额共:5858
存 1096 元 现在余额共:6954
存 1258 元 现在余额共:8212
存 1617 元 现在余额共:9829
存 763 元 现在余额共:10592
存 954 元 现在余额共:11546
存 183 元 现在余额共:11729
存 1815 元 现在余额共:13544
存 1647 元 现在余额共:15191