java多线程(2):并发编程实践(二)

2014-11-24 02:42:53 · 作者: · 浏览: 1
l.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
* Condition实现生产消费实例
*
* Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。
*
* @author menergy
* DateTime: 13-12-31 上午10:12
*/
public class ConditionTest {
public static void main(String args[]){
final Lock lock = new ReentrantLock();
final Condition produced = lock.newCondition();
final Condition consumed = lock.newCondition();

//资源持有开关,假设产品架最多只能放3个
final AtomicInteger productNum = new AtomicInteger(0);

ExecutorService executorService = ExecutorServiceUtils.getExecutor("test", 10);
//5个生产者
for(int i = 0; i < 5; i++){
//生产
final int produceId = i;
executorService.execute(new Runnable() {
@Override
public void run() {
lock.lock();
try {
if (productNum.get() == 3){
System.out.println("产品架满,生产者" + produceId + "等待,产品数量:" + productNum.get());
//放弃锁,进入睡眠,等待消费者
consumed.await();
}
System.out.println("生产者" + produceId + "开始生产产品,产品数量:" + productNum.get());
// 生产产品
TimeUnit.MILLISECONDS.sleep(500);
productNum.getAndIncrement();
System.out.println("生产者" + produceId + "生产完,产品数量:" + productNum.get());
//唤醒某个等待的生产线程
produced.signal();
//唤醒所有等待的生产线程
//produced.signalAll();
}catch (InterruptedException e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
});
}

//5个消费者
for(int i = 0; i < 5; i++){
//消费
final int consumeId = i;
executorService.execute(new Runnable(){
@Override
public void run() {
lock.lock();
try {
if (productNum.get() == 0){
System.out.println("产品架空,消费者" + consumeId + "等待,产品数量:" + productNum.get());
//放弃锁,进入睡眠,等待生产者
produced.await();
}
System.out.println("消费者" + consumeId + "开始消费产品,产品数量:" + productNum.get());
// 生产产品
TimeUnit.MILLISECONDS.sleep(300);
productNum.getAndDecrement();
System.out.println("消费者" + consumeId + "消费完,产品数量:" + productNum.get());
//唤醒某个等待的消费线程
consumed.signal();
//唤醒所有等待的消费线程
//consumed.signalAll();
}catch (InterruptedException e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
});
}

}
}

第3章:线程计数器CountDownLacth

第0节:札记

* CountDownLatch 是一个通用同步工具,它有很多用途。
* 将计数 1 初始化的 CountDownLatch 用作一个简单的开/关锁存器,或入口:
* 在通过调用 countDown() 的线程打开入口前,所有调用 await 的线程都一直在入口处等待。
* 用 N 初始化的 CountDownLatch 可以使一个线程在 N 个线程完成某项操作之前一直等待,
* 或者使其在某项操作完成 N 次之前一直等待。

第1节:实例

package com.mcc.core.test.thread;

import com.mcc.core.concurrent.ExecutorServiceUtils;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;

/**
* CountDownLacth线程计数器使用实例
*
* @author menergy
* DateTime: 13-12-27 下午2:39
*/
public class CountDownLacthTest {

public static void main(String args[]){
// 实例化线程计数器
int size = 3;
final CountDownLatch lacth = new CountDownLatch(size);
Executor executor = ExecutorServiceUtils.getExecutor("test",size);
for(int i = 0; i < 3; i++){
final int threadNum = i;
executor.execute(new Runnable(){
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread running:" + threadNum);
lacth.countDown();
}
});
}
// 主线程等待子线程,一直到程序计数器为0
try {
lacth.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main trhread finished !");
}

}

第4章:线程计数器(栅栏)CyclicBarrier

第0节:札记

* CyclicBarrier类似于CountDownLatch也是个计数器,
* 不同的是CyclicBarrier数的是调用了CyclicBarrier.await()进入等待的线程数,
* 当线