1、Java

当要使用线程去执行一个任务时,可以使用ExecutorService.submit(new Callable);

这样可以不影响其他的业务的执行,但是在线程中的异常不能捕获到,也不能知道线程的执行情况;

首先创建一个固定大小堵塞的线程池:

public class O2oThreadPoolExecutor extends ThreadPoolExecutor {

private static final Logger logger = LoggerFactory.getLogger(O2oThreadPoolExecutor.class);

private static ExecutorService executor = new O2oThreadPoolExecutor(2, 100, 60, TimeUnit.SECONDS,

new ArrayBlockingQueue(500), new RejectedExecutionHandlerImpl());

private static int MAX_CONCURRENCY = 0;

public static ExecutorService getInstance(){

return executor;

}

public O2oThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,

BlockingQueue workQueue, RejectedExecutionHandler handler) {

super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);

}

@Override

public void shutdown() {

printThreadPoolInfo("Shutdown");

super.shutdown();

}

@Override

protected void beforeExecute(Thread t, Runnable r) {

printThreadPoolInfo("Before execute");

super.beforeExecute(t, r);

}

@Override

protected void afterExecute(Runnable r, Throwable t) {

printThreadPoolInfo("After execute");

super.afterExecute(r, t);

}

private void printThreadPoolInfo(String subject){

int runningTasks = getActiveCount();

MAX_CONCURRENCY = runningTasks > MAX_CONCURRENCY ? runningTasks : MAX_CONCURRENCY;

logger.info("{}, pool size:{}, running task:{}, pending task:{}, max concurrency:{}.",

subject,getPoolSize(),getActiveCount(),getQueue().size(),MAX_CONCURRENCY);

}

}

然后实现RejectedExecutionHandler,主要是当拒绝之后,重新put进去,防止丢失

public class RejectedExecutionHandlerImpl implements RejectedExecutionHandler {

@Override

public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {

if(!executor.isShutdown()){

try{

executor.getQueue().put(r);

}catch(InterruptedException e){

}

}

}

}

在然后定义线程需要执行的任务,实现Callable接口

public class TradeStatisticsTask implements Callable {

private final static Log logger = LogFactory.getLog(TradeStatisticsTask.class);

private UserTradeStatisticsRequestDTO userTradeStatisticsRequestDTO;

private UserTradeStatisticsService userTradeStatisticsService;

private static final String TRADE_STATISTICS_CHANGE_LOCK = "trade_statistics_change_lock";

private static final int TRADE_STATISTICS_CHANGE_LOCK_EXPIRE = 1;

public TradeStatisticsTask(UserTradeStatisticsService userTradeStatisticsService,UserTradeStatisticsRequestDTO userTradeStatisticsRequestDTO){

this.userTradeStatisticsRequestDTO = userTradeStatisticsRequestDTO;

this.userTradeStatisticsService = userTradeStatisticsService;

}

@Override

public Long call() throws Exception {

logger.info("TradeStatisticsTask的insert任务:"+JSONUtils.toJsonString(this.userTradeStatisticsRequestDTO));

O2oLock lock = new O2oRedisLock(TRADE_STATISTICS_CHANGE_LOCK + userTradeStatisticsRequestDTO.getBankCardNumber()+userTradeStatisticsRequestDTO.getUserId(),

TRADE_STATISTICS_CHANGE_LOCK_EXPIRE);

if (lock.tryLock(TRADE_STATISTICS_CHANGE_LOCK_EXPIRE)) {

try{

//先判断在统计数据中是否有该用户、银行卡、当天的记录,如果没有,则插入,否则更新

Long userId = this.userTradeStatisticsRequestDTO.getUserId();

String bankCardNumber = this.userTradeStatisticsRequestDTO.getBankCardNumber();

String tradeYearMouthDay = this.userTradeStatisticsRequestDTO.getTradeYearMouthDay();

UserTradeStatistics tradeParam = userTradeStatisticsService.queryUserTradeByUserIdAndBankCardNum(tradeYearMouthDay, userId, bankCardNumber);

if(tradeParam != null){

logger.info("需要更新的tradestatistics是:"+JSONUtils.toJsonString(tradeParam));

BigDecimal dayAmount = this.userTradeStatisticsRequestDTO.getDayAmount().add(tradeParam.getDayAmount());

tradeParam.setDayAmount(dayAmount);

userTradeStatisticsService.update(tradeParam);

return tradeParam.getId();

}else{

logger.info("开始插入统计数据");

UserTradeStatistics userTradeStatistics = new UserTradeStatistics();

BeanMapper.copy(this.userTradeStatisticsRequestDTO, userTradeStatistics);

return userTradeStatisticsService.insert(userTradeStatistics);

}

}catch(Exception e){

logger.error("插入更新数据失败", e);

return null;

}

}else{

logger.info("被锁住了。。。。");

return null;

}

}

}

最后在业务层,调用线程执行

TradeStatisticsTask task = new TradeStatisticsTask(userTradeStatisticsService,userTradeStatisticsRequestDTO);

O2oThreadPoolExecutor.getInstance().submit(task);

2、guava

前面三步和java一样,只是在业务层处理层改成了guava的方式去处理线程的调用,使用guava调用是可以抓到线程运行时的异常、并知道线程是否运行成功;

TradeStatisticsTask task = new TradeStatisticsTask(userTradeStatisticsService,userTradeStatisticsRequestDTO);

// O2oThreadPoolExecutor.getInstance().submit(task);

//方法1:可以直接得到Future的返回值,或者处理错误情况

ListeningExecutorService executorService = MoreExecutors.listeningDecorator(O2oThreadPoolExecutor.getInstance());

final ListenableFuture future = executorService.submit(task);

Futures.addCallback(future, new FutureCallback() {

@Override

public void onFailure(Throwable e) {

logger.error("线程执行失败", e);

}

@Override

public void onSuccess(Long message) {

logger.info("receive message :" + message);

}

});

//方法2:监听Future,对原生Future扩展增强,ListenFuture可以帮忙检测Future是否执行完成,如果完成就自动调用回调函数

future.addListener(new Runnable(){

@Override

public void run() {

try {

logger.info("receive message :" + future.get());

} catch (Exception e) {//主要是InterruptedException、ExecutionException出错

logger.error("get message error :", e);

}

}

}, executorService);

java guava_多线程(java和guava两种方式):相关推荐

  1. Java中线程的创建有两种方式

    Java中继承thread类与实现Runnable接口的区别 Java中线程的创建有两种方式: 1.  通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中 2.  通过 ...

  2. java 深克隆_Java实现深克隆的两种方式

    序列化和依次克隆各个可变的引用类型都可以实现深克隆,但是序列化的效率并不理想 下面是两种实现深克隆的实例,并且测试类对两种方法进行了对比: 1.重写clone方法使用父类中的clone()方法实现深克 ...

  3. java的websocket_java 实现websocket的两种方式实例详解

    一.介绍 1.两种方式,一种使用tomcat的websocket实现,一种使用spring的websocket 2.tomcat的方式需要tomcat 7.x,JEE7的支持. 3.spring与we ...

  4. Java Spark之创建RDD的两种方式和操作RDD

    首先看看思维导图,我的spark是1.6.1版本,jdk是1.7版本 spark是什么?  Spark是基于内存计算的大数据并行计算框架.Spark基于内存计算,提高了在大数据环境下数据处理的实时性, ...

  5. websocket java 例子_java 实现websocket的两种方式实例详解

    目录 一.介绍 1.两种方式,一种使用tomcat的websocket实现,一种使用spring的websocket 2.tomcat的方式需要tomcat 7.x,JEE7的支持. 3.spring ...

  6. Java中类加载器获取的两种方式

    import org.junit.Test;import java.io.FileInputStream; import java.io.IOException; import java.io.Inp ...

  7. JAVA与PLC通讯读取数据(两种方式)

    第一种方式(s7connector) S7官网:S7Connector - Documentation,有简单的读写操作参考. 1.创建maven工程引入依赖 <dependency>&l ...

  8. Java代码实现MD5加密的两种方式

    MD5的全称是Message-Digest Algorithm 5 (信息-摘要算法),在90年代初,由MIT Laboratory for Computer Scientce 和RSA Data S ...

  9. Java面试题:线程实现的两种方式及匿名内部类实现

    QUESTION:线程实现的两种方式及匿名内部类实现 ANSWER: 1.多线程两种实现方式 (1)继承Thread     * 定义类继承Thread     * 重写run方法     * 把新线 ...

  10. idea中java程序打jar包的两种方式(超详细)

    java程序打成的jar包有两种类型,一种是可直接执行的runnable jar文件,另一种是包含多个主类,运行时需要指定主类全类名的jar包,下面我们细说在idea中两种jar包的打包方法及执行ja ...

最新文章

  1. DOM---文档对象模型(Document Object Model)的基本使用
  2. 博客园Markdown新建笔记
  3. Linux第二周学习笔记(11)
  4. 设计模式之简单工厂模式学习笔记
  5. 值“MT_StaticRelease”不匹配值“MD_DynamicRelease”
  6. php管理用户名和密码,管理员用户名/密码不适用于PHP
  7. gin gorm插入数据
  8. 在tomcat中部署mule项目
  9. java 异常机制_深入理解Java异常处理机制
  10. MaxCompute 费用暴涨之新增SQL分区裁剪失败
  11. 2021年移动市场报告.pdf
  12. android开发板功能,Android中NFC模块PN532开发板应用/原理图/PCB等全部资料
  13. python实时策略_Python策略模式
  14. nlp-tutorial代码注释3-3,双向RNN简介
  15. SpringBoot+Dubbo实战demo
  16. OpenCv —— 检测车牌号(附完整源码)
  17. Python实现LBP算法
  18. 关于蓝天准系统换京东方屏后不显bios的解决方案
  19. python怎样开发软件_Python是怎么编写软件的?
  20. blowfish java_Java语言实现Blowfish加密算法完整代码分享

热门文章

  1. GJM:C# WinForm开发系列 - DataGridView 使用方法集锦 [转载]
  2. 十五的学习日记20160926-你不知道的JS笔记/
  3. javascript jquery ajax动态提交多个参数 api测试
  4. 让visio保存背景透明的图片。
  5. DotNet 学习笔记
  6. 集合php,php function集合
  7. softmax函数_反向传播之一:softmax函数
  8. C4D立体数字设计灵感,适合庆典应用|这波用得6啊!
  9. 难以拒绝的中国风雅致新年元旦海报来袭
  10. 现代抽象UI素材背景3D流畅的造型(样条)|轻松地为Web创建3D体验