最近项目要用到多线程处理任务。
写了个线程工具。
用到了JDK的多线程工具,信号量Semaphore及计数器CountDownLatch
Semaphore用来控制任务的提交速率
当所有任务被submit后, 执行await(time), 等待计数器清零后手动关闭线程池
package org.leo.concurrent;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/**
* 带有信号量及计数器的多线程线程池
* <p>semaphore用来控制任务的提交速率,countDownLatch</p>
* <br/>信号量及线程数为 m, 任务数n, 一般n较大于m 如n=100,m=8
* @author Leo
*/
public class SemaphoreCountDownExecutor {
private Semaphore semaphore;
private CountDownLatch countDownLatch;
private ExecutorService executor;
/**
* 对象初始化
* @param semaphorePermits
* @param count
*/
public SemaphoreCountDownExecutor(final int semaphorePermits,final int count) {
semaphore = new Semaphore(semaphorePermits);
executor = Executors.newCachedThreadPool();
countDownLatch = new CountDownLatch(count);
}
/**
* 等待计数器归零, 并设置超时时间
* @param timeSeconds
*/
public void await(final long timeSeconds){
try {
if(timeSeconds<=0)
countDownLatch.await(60*60, TimeUnit.SECONDS);
else
countDownLatch.await(timeSeconds, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
executor.shutdown();/*使用Executors.newCachedThreadPool(),也没必要手动关闭*/
}
}
/**
* 提交一个任务到线程池,获取一个信号量并计数器减一
* @param command
* @throws InterruptedException
*/
public void submit(final Runnable command) throws InterruptedException {
semaphore.acquire(); /*接收一个信号量,此处可能抛出InterruptedException*/
try {
executor.execute(new Runnable() {
@Override
public void run() {
//run中是同步执行
try {
command.run();
} finally {
semaphore.release();
countDownLatch.countDown();
}
}
});
} catch (Exception e) {/*//捕获线程池异常时, 释放信号及计数器-1*/
countDownLatch.countDown();
semaphore.release();
}
}
public static void main(String[] args) {
final SemaphoreCountDownExecutor executor = new SemaphoreCountDownExecutor(10, 100);
for (int i = 0; i < 100; i++) {
final int fi = i;
try {
executor.submit(new Runnable() {
@Override
public void run() {
System.out.println(fi+","+Thread.currentThread().getName());
try {
Thread.sleep(new Random().nextInt(1500));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
executor.await(30);
System.out.println("end");
}
}