线程池的使用框架

    线程池可以认为是回调的方式。将匿名内部类传递给调用的线程。等线程池做完后,就可以调用内部类的方法。


     下面代码展示了一个请求(实际上是会有多个请求,这里只做一个demo)到来,后端用多线程回调的方式找到对应的数据源的过程。

    程序只有一下几个类:

       

    首先是实现ThreadFactory的工厂类,可以对线程进行命名。Daemon会在jvm退出后继续工作。

package callback;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.ThreadFactory;

public class NamedThreadFactory implements ThreadFactory {
	private final AtomicInteger threadNumber = new AtomicInteger(1);
	
	private final String namePrefix;
	
	private final boolean makeDaemons;
	
	private final ThreadGroup group;
	
	public NamedThreadFactory(String poolName) {
		this(poolName, false);
	}
	
	public NamedThreadFactory(String namePrefix, boolean makeDaemons) {
		this.namePrefix = namePrefix;
        this.makeDaemons = makeDaemons;
        this.group = Thread.currentThread().getThreadGroup();
	}
	
	 public Thread newThread(Runnable runnable) {
	        Thread ret = new Thread(group, runnable, namePrefix + "#" + threadNumber.getAndIncrement());
	        // java虚拟机退出后也不会终止的线程
	        ret.setDaemon(makeDaemons);
	        return ret;
	    }

	    public ThreadGroup getThreadGroup() {
	        return group;
	    }
}

    WorkUnit类,定义了选择的线程池,以及线程池的各项操作,如submit()函数,getResult()函数等。getResult函数调用了回调函数。即实现了callback的匿名内部类中callback()函数。

    使用泛型,因为call()、callback()函数返回类型可以多样,这样写更通用。使用CompletionService,对main方法定义的pool进一步封装。

     

package callback;

import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class WorkUnit<T> {
	private static final long DEFAULT_TIMEOUT = 10 * 60 * 1000;
	
	private CompletionService<T> completion;
	private AtomicInteger taskCount;
	private long timeout;
	
	public WorkUnit(Executor pool, long timeout) {
		completion = new ExecutorCompletionService<T>(pool);
		this.taskCount = new AtomicInteger();
		this.timeout = timeout;
	}
	
	public WorkUnit(Executor pool) {
		this(pool, DEFAULT_TIMEOUT);
	}
	
	public void submit(Runnable runnable) {
		completion.submit(runnable, null);
		taskCount.incrementAndGet();
	}
	
	public boolean waitForCompletion() {
		boolean success = true;
        for (int i = 0; i < taskCount.intValue(); i++) {
            try {
                Future<T> r = completion.take();
                r.get(timeout, TimeUnit.MILLISECONDS);
            } catch (Exception e) {
//                logger.error("wait for execute completion failed,e=" + e, e);
                success = false;
            }
        }
        return success;
	}
	public void submit(Callable<T> callable) {
        completion.submit(callable);
        taskCount.incrementAndGet();
    }

    public void getResult(WorkUnitCallback<T> WorkUnitCallback) throws Exception {
        for (int i = 0; i < taskCount.intValue(); i++) {
            Future<T> f = completion.take();
            WorkUnitCallback.callback(f.get(timeout, TimeUnit.MILLISECONDS));
        }
    }
}

    WorkUnitCallback接口,只定义了callback函数的声明。方便main方法采用匿名内部类的方式定义不同的callbcak()方法。main方法中把这个实现了WorkUnitCallback的匿名内部类传递给WorkUnit,在线程池做完相关的操作后,就会调用callback方法把结果放到List容器。

 

package callback;

public interface WorkUnitCallback<T> {
	void callback(T t);
}

    Main类,程序的执行入口。重要的是两个匿名内部类——call()和callback()。调用WorkUnit去执行。

    StandardDataCoreRequest是请求类。可以忽略不看。

     

package callback;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;


public class Main {
	// list多线程方法
	public static List<Map<String, Object>> responses = Collections.synchronizedList(new LinkedList<Map<String, Object>>());
	// NamedThreadFactory用途在于给创建的线程起名字,这样可以在控制台、日志显示是哪个线程
	protected static Executor WORKER_POOL = Executors.newFixedThreadPool(10, new NamedThreadFactory("KeyWordReportExecutor",true));
	public static void main(String[] args) throws Exception {
		StandardDatacoreRequest request = new StandardDatacoreRequest();
		List<StandardDatacoreRequest> requestGroups = new LinkedList<StandardDatacoreRequest>();
		requestGroups.add(request);
		WorkUnit<List<Map<String, Object>>> unit = new WorkUnit<List<Map<String, Object>>>(WORKER_POOL,
                1000L);
	
		for (final StandardDatacoreRequest req : requestGroups) {
			unit.submit(new Callable<List<Map<String, Object>>>() {
				  @Override
                  public List<Map<String, Object>> call() throws Exception {
                      return requestDataCore(req);
                  }
			});
		}
		
		 unit.getResult(new WorkUnitCallback<List<Map<String, Object>>>() {
             @Override
             public void callback(List<Map<String, Object>> t) {
                 if (t != null && !t.isEmpty()) {
                     responses.addAll(t);
                 }
             }
         });
	}
	
	public static List<Map<String, Object>> requestDataCore(StandardDatacoreRequest req) {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		System.out.println(134);
		return list;
	}
}

StandardDataCoreRequest和程序相关性不大。是写的一个请求类。

package callback;

import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;

import org.apache.commons.beanutils.BeanUtils;

public class StandardDatacoreRequest implements Cloneable {
//    private static Set<DatacoreColumn> EMPTY_DATACORECOLUMN = new HashSet<DatacoreColumn>();
    private Random random = new Random();
    private long logId = generateLogId();// 每个请求分配一个ID,唯一对应一个请求
    private Set<Long> userid;
    private Date beginTime;
    private Date endTime;
//    private TimeColumnGranularity timeColumnGranularity = TimeColumnGranularity.Daily;// 请求数据的time列,默认为分日(即,数据以哪种时间粒度呈现)
//    private Set<DatacoreColumn> idColumns;// 请求数据的id列(即,包含哪些维度)
//    private Set<DatacoreColumn> dataColumns;// 请求数据的data列(即,包含哪些数据指标)
//    private InCondition[] idConditions;// 具体的id集合,可指定多个层级(即,要请求物料范围)
//    private Set<DatacoreColumn> sumByColumns;// 根据哪个维度进行分维度求和
//    private Limit limit;// 分页参数,limit m,n
//    private Orders orderBy;// 排序列
    private boolean needSum;
    private int weekDayStartFrom = 1;
    private Set<String> processConf = new HashSet<String>(); // 特殊处理的一些标志集
//    private FamilyName family = FamilyName.FC;//区分报告来源家族,比如凤巢,知心教育等
//    private SQLCondition filterCondition; // 过滤条件
    private boolean isKeyWordOneDayRequest; //是否为关键词报告ID预取请求 
    private Integer reportType; // 请问报告类型

    /**
     * @return the reportType
     */
    public Integer getReportType() {
        return reportType;
    }

    /**
     * @param reportType the reportType to set
     */
    public void setReportType(Integer reportType) {
        this.reportType = reportType;
    }

//    public String getMD5ForRequest() {
//        ToStringBuilder str = new ToStringBuilder(this);
//        str.append(userid).append(beginTime).append(endTime).append(timeColumnGranularity).append(idColumns).append(
//                dataColumns).append(idConditions).append(limit).append(orderBy).append(weekDayStartFrom);
//        try {
//            MessageDigest md5 = MessageDigest.getInstance("md5");
//            byte[] md5Bytes = md5.digest(str.toString().getBytes("GBK"));
//            StringBuilder sb = new StringBuilder();
//            for (byte b : md5Bytes) {
//                sb.append(String.format("%02x", b));
//            }
//            return sb.toString();
//        } catch (Exception e) {
//            throw new RuntimeException("generate md5 failed");
//        }
//    }

    /**
     * 生成近似唯一的ID,用于标识每个请求 <br>
     * 在不同毫秒内,任意请求的ID不会重复 <br>
     * 在同一毫秒内,两个请求ID重复的概率约为1/65536
     * 
     * @return
     */
    private long generateLogId() {
        long now = System.currentTimeMillis();
        long rand = random.nextLong() & 0xFFFF;
        return now << 16 | rand; // 41 bits 系统时间 + 16 bits 随机数
    }

    public void addProcessConf(String... processorConfs) {
        if (processorConfs != null && processorConfs.length > 0) {
            this.processConf.addAll(Arrays.asList(processorConfs));
        }
    }

    public boolean hasProcessConf(String conf) {
        return this.processConf.contains(conf);
    }

//    @Override
//    public String toString() {
//        return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString();
//    }

    //  org.apache.commons.beanutils
    @Override
    public StandardDatacoreRequest clone() {
        StandardDatacoreRequest obj = null;
        try {
            obj = (StandardDatacoreRequest) BeanUtils.cloneBean(this);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        obj.logId = generateLogId();
        return obj;
    }

    public Set<String> getProcessConf() {
        return processConf;
    }

    public void setProcessConf(Set<String> processConf) {
        this.processConf = processConf;
    }

    public boolean isNeedSum() {
        return needSum;
    }

    public void setNeedSum(boolean needSum) {
        this.needSum = needSum;
    }

    public int getWeekDayStartFrom() {
        return weekDayStartFrom;
    }

    public void setWeekDayStartFrom(int weekDayStartFrom) {
        this.weekDayStartFrom = weekDayStartFrom;
    }

    /**
     * 用于标识每个请求的ID <br>
     * 该ID近似唯一,但不保证严格的唯一性,因此不能用于实际业务逻辑 <br>
     * 在不同毫秒内,任意请求的ID不会重复 <br>
     * 在同一毫秒内,两个请求ID重复的概率约为1/65536
     * 
     * @return
     */
    public long getLogId() {
        return logId;
    }

    public Set<Long> getUserid() {
        return userid;
    }

    public void setUserid(Set<Long> userid) {
        this.userid = userid;
    }

    public Date getBeginTime() {
        return beginTime;
    }

    public void setBeginTime(Date beginTime) {
        this.beginTime = beginTime;
    }

    public Date getEndTime() {
        return endTime;
    }

    public void setEndTime(Date endTime) {
        this.endTime = endTime;
    }


    public void setKeyWordOneDayRequest(boolean isKeyWordOneDayRequest) {
        this.isKeyWordOneDayRequest = isKeyWordOneDayRequest;
    }
}


    


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值