在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法。
以下是本文目录大纲:
一.CountDownLatch用法
二.CyclicBarrier用法
三.Semaphore用法
一.CountDownLatch用法
CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能。比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。
CountDownLatch类只提供了一个构造器:
1
public CountDownLatch(int count) { }; //参数count为计数值
然后下面这3个方法是CountDownLatch类中最重要的方法:
public void await() throws InterruptedException { }; //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
public class Test {
public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(2);
new Thread(){
public void run() {
try {
System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
Thread.sleep(3000);
System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
}.start();
new Thread(){
public void run() {
try {
System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
Thread.sleep(3000);
System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
}.start();
try {
System.out.println("等待2个子线程执行完毕...");
latch.await();
System.out.println("2个子线程已经执行完毕");
System.out.println("继续执行主线程");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
用来验证StringBufffer和StringBuilder的线程安全性
package ThreadStudy;
import java.util.concurrent.CountDownLatch;
public class Thread06 extends Thread {
private static final int countThread = 100;
private static StringBuffer buffer = new StringBuffer();
private static StringBuilder builder = new StringBuilder();
private static CountDownLatch latch1 = new CountDownLatch(countThread);
@Override
public void run() {
System.out.println("线程" +Thread.currentThread().getName());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("线程" +Thread.currentThread().getName() +"After Thead");
buffer.append("12345");
builder.append("12345");
latch1.countDown();
System.out.println("线程" +Thread.currentThread().getName() +"run end--->");
}
public static void main(String[] args) throws InterruptedException {
for (int i = 1; i <= countThread; i++) {
Thread06 myThread = new Thread06();
myThread.start();
}
latch1.await();
System.out.println("StringBuffer-->:" + buffer.length() + "---》StringBuilder-->" + builder.length());
}
}
执行结果:
自定义实现类似于CountDownLatch这样的类,当然自己试着写着玩的,肯定会有好多没有考虑到的
package cn.ok.http.utils;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static cn.ok.http.utils.DaemonThreadTest.stringBuffer;
import static cn.ok.http.utils.DaemonThreadTest.stringBuilder;
public class DaemonThreadTest {
private static int countThread = 1000;
static DaemonThread daemoThread = new DaemonThread(countThread);
static StringBuffer stringBuffer = new StringBuffer(); //线程安全
static StringBuilder stringBuilder = new StringBuilder(); //非线程安全
public static void main(String[] args) throws InterruptedException {
System.out.println("main开始");
StringThread buffer = new StringThread();
for (int i = 0; i < countThread; i++) {
Thread thread = new Thread(buffer);
thread.start();
}
daemoThread.aWaite();
System.out.println("Thred 执行完毕》》》》");
System.out.println("StringBuffer-->:" + stringBuffer.length() + "---》StringBuilder-->" + stringBuilder.length());
System.out.println("StringBuffer-->: " + stringBuffer.toString());
System.out.println("StringBuilder-->:" + stringBuilder.toString());
}
}
/**
* desc:类似于ConutDownLatch类
*/
class DaemonThread {
private int count; // 要运行线程个数
private Lock lock = new ReentrantLock();
private Boolean status = true;
public int getCount() {
return count;
}
public DaemonThread(int count) {
this.count = count;
}
public void countDown() {
lock.lock();
try {
this.count = this.count - 1;
// System.out.println("当前执行线程为Lock:" + Thread.currentThread().getName() + " countDown " + this.count);
} catch (Exception e) {
} finally {
if (this.count == 0) {
status = false;
}
lock.unlock();
}
}
public void aWaite() throws InterruptedException {
if (status) {
Thread.sleep(4);
aWaite();
}
}
}
/**
* desc: 测试StringBuffer和StringBuilder类的线程安全性
*/
class StringThread implements Runnable {
@Override
public void run() {
try {
System.out.println("线程" + Thread.currentThread().getName());
Thread.sleep(1000);
for (int i = 0; i < 100; i++) {
stringBuffer.append("ABC");
stringBuilder.append("ABC");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
DaemonThreadTest.daemoThread.countDown();
}
}
当然也可以直接这样用:
package book.thread.pool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class MyRunnable implements Runnable {
@Override
public void run() {
try {
System.out.println("线程" + Thread.currentThread().getName());
Thread.sleep(1000);
for (int i = 0; i < 100; i++) {
ExecutorServiceDemo.stringBuffer.append("ABC");
ExecutorServiceDemo.stringBuilder.append("ABC");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ExecutorServiceDemo {
static StringBuffer stringBuffer = new StringBuffer();
static StringBuilder stringBuilder = new StringBuilder();
public static void main(String[] args) throws InterruptedException {
int countThread = 1000;
System.out.println("main 开始");
// 创建一个线程池对象,控制要创建几个线程对象。
ExecutorService pool = Executors.newFixedThreadPool(countThread);
for (int i = 0; i < countThread; i++) {
// 可以执行Runnable对象或者Callable对象代表的线程
pool.submit(new MyRunnable());
}
//结束线程池
pool.shutdown();
//这2个,默认为main线程和守护线程 Thread.enumerate
while (Thread.activeCount() != 2) {
}
System.out.println("StringBuffer-->:" + stringBuffer.length() + "---》StringBuilder-->" + stringBuilder.length());
System.out.println("main退出");
}
}