业务中要把pdf转为pngs,作以下service
public PageResult findByUrl(String url) {
if(!Pdf2Img.checkPdf(url))
return PageResult.genFail("非pdf文件");
Attach attach = attachDao.findByUrl(url);
if(attach == null) {
AttachThread mt1=new AttachThread(url);
new Thread(mt1).start();
return PageResult.genFail("文件未准备好,请稍后再试");
} else {
String res = attach.getUrl_new();
String [] imgs = res.split(",");
return PageResult.genSuccess((Object)imgs);
}
}
传入pdf文件url,返回pngs文件url,
首先查找该附件有没有转过过,若转换过,直接返回转换后的url,若没转换过,新建线程进行转换
然而pdf转换png消耗资源及时间较大,若有两个线程同时请求转换,则会重复转换,浪费资源,故作同步处理如下:
public class AttachThread implements Runnable {
private String url;
private static AtomicInteger serailCount = new AtomicInteger(1);
private Integer serial;
public AttachThread(String _url) {
url = _url;
serial = serailCount.getAndIncrement();
}
@Override
public void run(){
AttachDao attachDao = (AttachDao)SpringUtil.getBean(AttachDao.class);
Attach attach = attachDao.findByUrl(url);
if(attach == null) {
System.out.println(String.format("线程%d,类锁,所有线程阻塞", serial));
synchronized (AttachThread.class) {
attach = attachDao.findByUrl(url);
if(attach == null) {
String url_new = Pdf2Img.comeGetIdList(url);
if(url_new != null || !"".equals(url_new)) {
attach = new Attach();
attach.setCreate_date(new Date());
attach.setUrl_old(url);
attach.setUrl_new(url_new);
attachDao.save(attach);
}
System.out.println(String.format("线程%d完成业务,释放类锁,第一线程应该走此路径", serial));
} else {
System.out.println(String.format("线程%d取得锁之后发现业务已经处理,非第一线程应该走此路径", serial));
}
}
} else {
System.out.println(String.format("线程%d已经转换,不用锁,原则上不走此路径", serial));
}
}
}
AttachDao attachDao = (AttachDao)SpringUtil.getBean(AttachDao.class);
这一段是在此非spring托管的线程类中调用spring托管的类,详细见
http://blog.csdn.net/silyvin/article/details/70832415
http://www.cnblogs.com/vinozly/p/5223147.html
Attach attach = attachDao.findByUrl(url);
if(attach == null) {
如果没有找到转换后的png url,则开启转换程序
System.out.println(String.format("线程%d,类锁,所有线程阻塞", serial));
synchronized (AttachThread.class) {
attach = attachDao.findByUrl(url);
if(attach == null) {
String url_new = Pdf2Img.comeGetIdList(url);
if(url_new != null || !"".equals(url_new)) {
attach = new Attach();
attach.setCreate_date(new Date());
attach.setUrl_old(url);
attach.setUrl_new(url_new);
attachDao.save(attach);
}
System.out.println(String.format("线程%d完成业务,释放类锁,第一线程应该走此路径", serial));
} else {
System.out.println(String.format("线程%d取得锁之后发现业务已经处理,非第一线程应该走此路径", serial));
}
}
开启同步,同步块中,第一线程,再次判断是否转换,其他线程阻塞
测试,同时进行4次请求,输出
线程1,类锁,所有线程阻塞
线程2,类锁,所有线程阻塞
线程3,类锁,所有线程阻塞
线程4,类锁,所有线程阻塞
线程1完成业务,释放类锁,第一线程应该走此路径
线程4取得锁之后发现业务已经处理,非第一线程应该走此路径
线程3取得锁之后发现业务已经处理,非第一线程应该走此路径
线程2取得锁之后发现业务已经处理,非第一线程应该走此路径