最近开始做了一个关于多线程的项目,这个项目是关于淘宝图片认证防伪项目,遇到的问题是大批图片认证上传业务,预计每天的流量是10g以上。大批图片我们不能进行单线程运作,否则问题就大了。理论是多线程技术,负载均衡技术,高速缓存技术可以解决这样的问题。想法是好的,问题就在技术方案和解决方案。
在jdk1.4以前没有concurrent包。提供的就是synchronized同步和wait,也没有线程池技术,但是在jdk5/6就不相同了。对于jdk1.4模拟实现:
public class TaskManagerQuene {
private LinkedList<String> taskQuene = new LinkedList<String>();
public void addTask(String task) throws InterruptedException {
synchronized (this.taskQuene) {
while (this.taskQuene.size() == 10) {
this.taskQuene.wait();
}
this.taskQuene.add(task);
this.taskQuene.notifyAll();
}
}
public String getTask() throws InterruptedException {
synchronized (this.taskQuene) {
String str = null;
while(this.taskQuene.size()==0){
this.taskQuene.wait();
}
str = this.taskQuene.remove();
this.taskQuene.notifyAll();
return str;
}
}
}
这样的写法很糟糕,如果处理不当,很容易造成线程死锁,可读性也差。不能进行手工解锁,采用jdk5/6实现手法就不一样了,如下:
public class TaskManageQuene {
private LinkedList<Runnable> taskUrlQuene;
private LinkedList<Runnable> taskImageDownload;
private Lock taskUrlLock = new ReentrantLock();
private Condition addTaskCondition = taskUrlLock.newCondition();
private Condition getTaskCondition = taskUrlLock.newCondition();
public TaskManageQuene() {
this.taskUrlQuene = new LinkedList<Runnable>();
}
public void addTask(Runnable task) {
taskUrlLock.lock();
try {
while (this.taskUrlQuene.size() == 10) {
this.addTaskCondition.await();
}
this.taskUrlQuene.add(task);
this.getTaskCondition.signalAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
taskUrlLock.unlock();
}
}
public Runnable getTask() {
taskUrlLock.lock();
Runnable run = null;
try {
while (this.taskUrlQuene.size() == 0) {
this.getTaskCondition.await();
}
run = this.taskUrlQuene.remove();
this.addTaskCondition.signalAll();
return run;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
}
return run;
}
}
注意:Condition对应wait,notify,这里我们随时都可以解锁,避免了线程死锁问题,这个线程的模式是
1.生产者-消费者2.生产者-消费者,第一消费者是第二个的生产者。
在jdk5/6提供了现成的线程池实现,
TaskProductExcutorPool taskProductExcutorPool = new TaskProductExcutorPool(taskQueue);
TaskCustomerExecutorPool taskCustomerExecutorPool = new TaskCustomerExecutorPool(taskQueue);
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(taskCustomerExecutorPool);
executorService.execute(taskProductExcutorPool);
taskCustomerExecutorPool.shutDown();
taskProductExcutorPool.shutDown();
executorService.shutdown();