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的两种方式_多线程(java和guava两种方式):相关推荐

  1. java 监控对象是什么_多线程-Java中的对象监视器是什么意思? 为什么要使用这个词?...

    多线程-Java中的对象监视器是什么意思? 为什么要使用这个词? 在阅读有关Java线程的文章时,我经常注意到这样的表达:"当前线程是该对象的监视器的所有者". 我的意思是:线程有 ...

  2. 西门子精智comfort系列面板下载程序的几种方法_参考手册(以太网+PN+USB方式)

    西门子精智comfort系列面板下载程序的几种方法_参考手册(以太网+PN+USB方式) 以太网及 PN/IE 方式下载 下载要求 以太网电缆 交叉线: 对电缆的具体要求最好采用T568B的交叉线序标 ...

  3. 【源码+图片素材】Java王者荣耀游戏开发_开发Java游戏项目【王者荣耀】1天搞定!!!腾讯游戏_Java课程设计_Java实战项目_Java初级项目

    王者荣耀是当下热门手游之一,小伙伴们是否想过如何制作一款属于自己的王者荣耀游戏呢? 本课程讲解了一个王者荣耀游戏的详细编写流程,即使你是刚入门Java的新手,只要你简单掌握了该游戏所需要的JavaSE ...

  4. JAVA共有几种窗体布局方式_在Java GUI程序开发中常见的三种布局管理器是什么

    答:FlowLayout 流式布局,从左到右,如果到边界就换行再从左到右. BorderLayout 边界布局(默认布局方式),按东西南北中五个方向来布局,默认是中.后设置在同样位置的控件会覆盖之前的 ...

  5. java中的单例_细说Java中的几种单例模式

    在Java中,单例模式分为很多种,本人所了解的单例模式有以下几种,如有不全还请大家留言指点: 饿汉式 懒汉式/Double check(双重检索) 静态内部类 枚举单例 一.饿汉式 image 饿汉式 ...

  6. java 同步解决不安全类_「JAVA」Java 线程不安全分析,同步锁和Lock机制,哪个解决方案更好...

    线程不安全 线程不安全的问题分析:在小朋友抢气球的案例中模拟网络延迟来将问题暴露出来:示例代码如下: public class ImplementsDemo { public static void ...

  7. java ee 的使用方法_改善Java EE生产支持技能的8种方法

    java ee 的使用方法 参与Java EE生产支持的每个人都知道这项工作可能很困难. 7/24寻呼机支持,多个事件和错误修复(要定期处理),来自客户和管理团队的压力,要求它们尽快解决生产问题并防止 ...

  8. java获取系统时间的几种方法_获取当前时间的几种方法整理(Java)

    在java中有很多方法可以取到系统时间,记一下最简单的那种 //使用Calendar 获取当前日期和时间 Calendar calendar = Calendar.getInstance(); // ...

  9. python猜拳游戏三局两胜制_猜拳游戏三局两胜------java实现代码

    package com.javasm.exerices02; import java.util.ArrayList; import java.util.List; import java.util.R ...

最新文章

  1. 归一化激活层的进化:谷歌Quoc Le等人利用AutoML 技术发现新型ML模块
  2. 干货丨从起源到具体算法,这是一份适合所有人读的深度学习综述论文
  3. 【记录】python多线程的使用 线程同步(LOCK和RLOCK) python与mysql数据库交互实现增加和查找 python的格式化输出
  4. 如何更改ubuntu的用户密码
  5. Dlib与OpenCV图片转换
  6. AcWing 499. 聪明的质监员
  7. mysql y_关于MySQL中Y和~问题
  8. 数据库事务的四个隔离级别
  9. webstore报 ESLint: Expected space or tab after '//' in comment.(spaced-comment)
  10. JavaScript学习(四十八)—原型对象的增删改查
  11. 数据--第37课 - 线索化二叉树
  12. [ 淘宝商城 ] 商城SEO
  13. c语言程序设计身高体重测评系统,C语言程序设计验.doc
  14. 1 Apache启动失败,请检查相关配置 √MySQL5 1已启动 解决方案
  15. CF546C. Soldier and Cards(队列+模拟)
  16. Codeforces Round #801 (Div. 2) D2(思维/dfs)
  17. 手把手系列--验证自己编写的STM32H750XBH6_ArtPi平台Keil MDK Flash下载算法
  18. 百度关键字优化精灵下载-批量免费百度关键词优化软件
  19. hsqldb mysql 语法_[spring batch]建表语句(hsqldb改mysql)
  20. 报表中的多维数据分析,并没有你想象的那么难!

热门文章

  1. Vite与webpack优势
  2. Java黑皮书课后题第3章:*3.5(给出将来的日期)编写一个程序,提示用户输入代表今天日期的数字(周日0周一1周二2)同时用户输入一个今天之后的天数代表将来某天的数字,然后显示这天是周几
  3. 2013年完美世界校园招聘笔试题
  4. KMP算法详解及各种应用
  5. 【git】强制覆盖本地代码(与git远程仓库保持一致)
  6. spring 之 init-method InitializingBean
  7. Ubuntu 16.04系统下配置cocos2dx-3.10
  8. 用UltraEdit判断打开文件的编码类型 用UltraEdit或notepad记事本查看文件编码格式 用UltraEdit查看当前文件编码...
  9. 解决cell循环利用造成的重复勾选
  10. storm安装笔记以及提交拓扑任务