线程池与缓存队列实现的异步线程管理器应用ThreadPoolManager 源码

业务场景

当系统A不关心系统B执行的结果时,建议使用异步多线程的形式通知B系统处理,以下多线程的案例就是使用线程池和队列的完成异步通知B系统的处理,废话不多说,上代码:

源码:


/**
 * com.hshc.threadpool.ThreadPoolManager.java
 * Copyright 2017 Lifangyu, Inc. All rights reserved.
 * PROPRIETARY/CONFIDENTIAL.Use is subject to license terms.
 */
package com.hshc.threadpool;

import lombok.extern.slf4j.Slf4j;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.*;

/**
 * Desc:线程池管理器
 *
 * @author lifangyu
 * @date 2017/12/8.
 */
@Slf4j
public class ThreadPoolManager {

private static ThreadPoolManager instance;

/**
 * 线程池维护线程的最少数量
 */
private static int COREPOOLSIZE = 4;

/**
 * 线程池维护线程的最大数量
 */
private static int MAXPOOLSIZE = 10;

/**
 * 线程池维护线程所允许的空闲时间
 */
private static int KEEPALIVETIME = 0;

/**
 * 线程池所使用的缓冲队列大小
 */
private static int WORKQUEUESIZE = 10;

/**
 * 消息缓冲队列
 */
Queue<T> msgQueue = new LinkedList<>();


/**
 * 非单例带参实例,重新创建一个实例[不推荐是使用]
 *
 * @param corepoolsize
 * @param maxpoolsize
 * @param keepalivetime
 * @param workqueuesize
 * @return ThreadPoolManager
 * @author lifangyu
 */
public static ThreadPoolManager newInstance(int corepoolsize, int maxpoolsize, int keepalivetime, int workqueuesize) {
    COREPOOLSIZE = corepoolsize;
    MAXPOOLSIZE = maxpoolsize;
    KEEPALIVETIME = keepalivetime;
    WORKQUEUESIZE = workqueuesize;
    instance = new ThreadPoolManager();
    return instance;
}

/**
 * 单例模式[推荐使用]
 *
 * @return ThreadPoolManager
 * @author lifangyu
 */
public static ThreadPoolManager getInstance() {
    if (instance == null) {
        synchronized (new Object()) {
            if (instance == null) {
                instance = new ThreadPoolManager();
            }
        }
    }
    return instance;
}


/**
 * 访问消息缓存的调度线程[很重要]
 * 查看是否有待定请求,如果有,则创建一个新的AccessDBThread,并添加到线程池中
 */
final Runnable accessBufferThread = new Runnable() {
    @Override
    public void run() {
        if (hasMoreAcquire()) {
            T vo = (T) msgQueue.poll();
            Runnable task = new CallBackThread(vo);
            threadPool.execute(task);
        }
    }
};

final RejectedExecutionHandler handler = new RejectedExecutionHandler() {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        log.info("线程ID:{} execute thread [{}]消息放入队列中重新等待执行", Thread.currentThread().getId(), ((CallBackThread) r).getVo().toString());
        msgQueue.offer(((CallBackThread<T>) r).getVo());
    }
};

/**
 * 管理数据库访问的线程池
 */
@SuppressWarnings({"rawtypes", "unchecked"})
final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(COREPOOLSIZE, MAXPOOLSIZE, KEEPALIVETIME,
        TimeUnit.SECONDS, new ArrayBlockingQueue(WORKQUEUESIZE), this.handler);

/**
 * 调度线程池
 */
final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(100);

@SuppressWarnings("rawtypes")
final ScheduledFuture taskHandler = scheduler.scheduleAtFixedRate(accessBufferThread, 0, 1, TimeUnit.SECONDS);

private boolean hasMoreAcquire() {
    return !msgQueue.isEmpty();
}

public void noticeCallBack(String url,T vo) {
    Runnable task = new CallBackThread<T>(url,vo);
    threadPool.execute(task);
}

}


/**
* com.hshc.threadpool.CallBackThread.java
* Copyright 2017 Lifangyu, Inc. All rights reserved.
* HuaShengHaoChe PROPRIETARY/CONFIDENTIAL.Use is subject to license terms.
*/
package com.hshc.threadpool;

import com.hshc.common.utils.PropertiesUtil;
import com.hshc.common.utils.RestHttpUtil;
import com.hshc.wh.eas.domain.EasVoucherInstorageRequestVo;
import com.hshc.wh.eas.domain.EasVoucherMaterialRequestVo;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
* Desc:TODO
*
* @author lifangyu
* @date 2017/12/8.
*/
@Slf4j
@Data
public class CallBackThread implements Runnable {

private String url;

private T vo;

public CallBackThread(T vo) {
    if (vo instanceof EasVoucherMaterialRequestVo) {
        this.url = PropertiesUtil.getConfigValueByKey("hshc.whapi.eas.material.url");

    } else if (vo instanceof EasVoucherInstorageRequestVo) {
        this.url = PropertiesUtil.getConfigValueByKey("hshc.whapi.eas.purchase.url");
    }
    log.info("CallBackThread.url:{}", url);
    this.vo = vo;
}

public CallBackThread(String url, T vo) {
    this.url = url;
    this.vo = vo;
}

@Override
public void run() {
    log.info("线程ID:{} execute callbackFeignClient.recharge start [url:{},param:{}] ", Thread.currentThread().getId(), url, vo.toString());
    // 需要异步执行的业务逻辑实现
    String result = RestHttpUtil.sendPost(url, vo);
    log.info("线程ID:{} execute callbackFeignClient.recharge end [result:{}] ", Thread.currentThread().getId(), vo.toString(), result);
}

}

说明

1.使用的jar:lombok;
2.消息缓存队列很重要:Queue<T> msgQueue,如果由于资源竞争线程执行失败,会进入到msgQueue缓存队列中,在任务执行完后会检查对列中是否有消息,有的话会再次执行不会有丢失的信息,可以通过本地大量数据多起几个实例验证此现象.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值