`

多线程的执行任务

阅读更多

    项目中在计算权限的时候有性能有问题,简单的使用多线程的方式改造了下,在这个地方记录一下,防止遗忘。

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.apache.commons.lang.StringUtils;

import com.xxx.zzz.account.model.Account;
import com.xxx.zzz.common.ServiceBeanFactory;
import com.xxx.zzz.common.exception.ZZZRuntimeException;
import com.xxx.zzz.common.log.LoggerHelper;
import com.xxx.zzz.resource.model.Resource;


public class ConcurrentAccountTreeCalculator {
	 private final static int MAX_THREAD = 20;
	 private final static int TASK_PER_THREAD = 5;
	 
	private static ExecutorService initExecutor(int taskNum){
		
		int threadNum = 0;
		if(taskNum / TASK_PER_THREAD >  MAX_THREAD){
			threadNum = MAX_THREAD;
		} else {
			threadNum = (taskNum / TASK_PER_THREAD) + 1;
		}
		return Executors.newFixedThreadPool(threadNum);
	}
	 
	public static Set<String> calculate(List<String> userNames,Resource resource){
		List<Future<String>> futures = new ArrayList<Future<String>>(); 
		
		Set<String> destNames = new HashSet<String>(userNames);
		
		int taskSize = userNames.size();
		ExecutorService exec = initExecutor(taskSize);
		
		List<Callable<String>> tasks = new ArrayList<Callable<String>>(taskSize);
		for(String userName : userNames){
			AccountTreeCalculator calculator = new AccountTreeCalculator(userName,resource);
			tasks.add(calculator);
		}
		
		try {
            for (Callable<String> callable : tasks) {
                futures.add(exec.submit(callable));
            }

            for (Future<String> future : futures) {
               String destUserName = future.get();
               if(StringUtils.isNotBlank(destUserName)){
            	   destNames.remove(destUserName);
               } 
            }
        } catch(Exception e){
        	LoggerHelper.err(ConcurrentAccountTreeCalculator.class, "计算人员权限出错", e);
        }
        
        return destNames;
	}
	 
	static class AccountTreeCalculator implements Callable<String> {
		private String userName;
		private Resource resource;
		
		public AccountTreeCalculator(String userName,Resource resource) {
			this.userName = userName;
			this.resource = resource;
		}

		@Override
		public String call() {
			try {
				Account account = ServiceBeanFactory.getAccountService().getByName(userName);
				
				if(account == null){
					throw new SpmRuntimeException(String.format("Can't find user:%s", userName));
				}
	
				boolean hasPermisison = ServiceBeanFactory.getResourceService().hasPermission(resource, account);
				if(hasPermisison) {
					return account.getName();
				} 
			} catch(Exception e){
				LoggerHelper.err(this.getClass(), "计算人员权限出错", e);
			}
			return null;
		}
	}
	 
}



    这个实现的非常简单,我这里就不解释了,AccountTreeCalculator实现了Callable接口,这个里面实现具体的计算逻辑,然后将任务提交给ExecutorService来进行计算,future.get()会等待子线程返回结果,所以整个程序很好理解。
    短小精悍但是比较有用。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics