线程池的使用框架

来源:互联网 发布:mysql 阻止连接半小时 编辑:程序博客网 时间:2024/05/22 22:45

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


     下面代码展示了一个请求(实际上是会有多个请求,这里只做一个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;    }}


    


0 0
原创粉丝点击