在项目中,我们的数据以位图的形式存放于Redis当中,一般一份数据在2M左右。每天做任务的时候会有大量的数据读写操作,产生较大的流量,导致带宽占用很高。所以,需要对读写进行并发的控制。下面是我的并发控制的实现(因为已经够用,所以就没有再考虑公平性、性能等问题)。
并发控制器:
package com.bin.ccrc;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 并发控制器
*/
public class CcrControl {
private volatile AtomicInteger curCcr = new AtomicInteger(0);
private volatile Object lock = new Object();
/**
* 执行指定任务,并做并发控制
* @param task
* @return
*/
public <T> T runTask(CcrTask<T> task) {
try {
// 检查是否可执行,不可执行则等待
synchronized (lock) {
while (curCcr.get() >= task.maxCcr()) {
try {
lock.wait();
} catch (InterruptedException e) {
// Exception handling
}
}
curCcr.incrementAndGet();
}
// 执行操作
return task.exec();
} catch (Exception e) {
// Exception handling
} finally {
// 释放并发数,唤醒等待线程
synchronized (lock) {
curCcr.decrementAndGet();
lock.notifyAll();
}
}
return null;
}
}
package com.bin.ccrc;
/**
* 抽象任务
*/
public interface CcrTask<T> {
/**
* 实际执行的操作
* @return
*/
public T exec();
/**
* 允许的最大并发数
* @return
*/
public int maxCcr();
}
具体任务:
package com.bin.ccrc;
/**
*具体任务
*/
public class ActualTask implements CcrTask<Integer> {
@Override
public Integer exec() {
// 执行任务
try {
// 模拟任务执行
System.out.println(Thread.currentThread().getName() + " is runing...");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 1;
}
@Override
public int maxCcr() {
return 2;
}
}
任务测试:
package com.bin.ccrc;
/**
* Test
*/
public class TaskTest {
private volatile static CcrControl ccrControlInstance;
private static CcrControl getCcrControlInstance() {
if (ccrControlInstance == null) {
synchronized (ActualTask.class) {
if (ccrControlInstance == null) {
ccrControlInstance = new CcrControl();
}
}
}
return ccrControlInstance;
}
/**
* run task
* @return
*/
public static int runTask() {
ActualTask task = new ActualTask();
int rs = getCcrControlInstance().runTask(task);
return rs;
}
public static void main(String[] args) {
for (int i = 0; i < 10000; i++) {
new Thread(new Runnable() {
@Override
public void run() {
TaskTest.runTask();
}
}, "t-" + i).start();
;
}
}
}