JAVA使用多线程进行数据处理
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*; /**
* 以下是伪代码,要根据自己的实际逻辑进行整合
*/
@Service
public class PushProcessServiceImpl implements PushProcessService { private final static Logger logger = LoggerFactory.getLogger(PushProcessServiceImpl.class); /**
*每个线程更新的条数
* 这表示每次执行五千条数据的推送操作
*/
private static final Integer LIMIT = 5000; /**
* 起的线程数
*/
private static final Integer THREAD_NUM = 5; /**
* 创建线程池
*
* - corePoolSize:线程核心参数选择了5
*
* - maximumPoolSize:最大线程数选择了核心线程数2倍数
*
* - keepAliveTime:非核心闲置线程存活时间直接置为0
*
* - unit:非核心线程保持存活的时间选择了 TimeUnit.SECONDS 秒
*
* - workQueue:线程池等待队列,使用 容量初始为100的 LinkedBlockingQueue阻塞队列
*
* 线程池拒绝策略,采用了默认AbortPolicy:直接丢弃任务,抛出异常。
*
*/
ThreadPoolExecutor pool = new ThreadPoolExecutor(THREAD_NUM, THREAD_NUM * 2, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100)); /**
* 执行推送任务
* @throws ExecutionException
* @throws InterruptedException
*/
public void pushData() throws ExecutionException, InterruptedException {
//计数器,需要保证线程安全
int count = 0; //这里从数据库查询出要推送数据总数,根据自己实际的来
Integer total = pushProcessMapper.getCountByState(0); logger.info("未推送数据条数:{}", total);
//计算需要循环多少轮
int num = total / (LIMIT * THREAD_NUM) + 1;
logger.info("要经过的轮数:{}", num); //统计总共推送成功的数据条数
int totalSuccessCount = 0;
for (int i = 0; i < num; i++) {
//使用集合来接收线程的运行结果,防止阻塞,接收线程返回结果
List<Future<Integer>> futureList = new ArrayList<>(32); //起THREAD_NUM个线程并行查询更新库,加锁
for (int j = 0; j < THREAD_NUM; j++) {
//使用 synchronized 来保证线程安全,保证计数器的增加是有序的
synchronized (PushProcessServiceImpl.class) {
int start = count * LIMIT;
count++;
/**
* 提交线程,用数据起始位置标识线程
* 这里前两个参数start和limit参数相当于执行sql
* limit start,limit
*
*/ Future<Integer> future = pool.submit(new PushDataTask(start, LIMIT, start));
//先不取值,防止阻塞,放进集合
futureList.add(future);
}
}
//统计本轮推送成功数据
for (Future f : futureList) {
totalSuccessCount = totalSuccessCount + (int) f.get();
}
}
//把数据库的推送标识更新为已推送(已推送!=推送成功),可以根据自己实际的来
pushProcessMapper.updateAllState(1); logger.info("推送数据完成,需推送数据:{},推送成功:{}", total, totalSuccessCount);
} /**
* 推送数据线程类
*/
class PushDataTask implements Callable<Integer> {
int start;
int limit;
int threadNo; //线程编号 PushDataTask(int start, int limit, int threadNo) {
this.start = start;
this.limit = limit;
this.threadNo = threadNo;
} @Override
public Integer call() throws Exception {
int count = 0;
//分页查询每次执行的推送的数据,查询数据
List<PushProcess> pushProcessList = pushProcessMapper.findPushRecordsByStateLimit(0, start, limit);
if (CollectionUtils.isEmpty(pushProcessList)) {
return count;
}
logger.info("线程{}开始推送数据", threadNo); /**
* 遍历需要更新的数据实体类
*/
for (PushProcess process : pushProcessList) {
//这里是执行推送请求,根据自己实际的来,也可以要处理的任务
boolean isSuccess = pushUtil.sendRecord(process); //根据主键更新推送是否成功状态标识
if (isSuccess) {
//推送成功
pushProcessMapper.updateFlagById(process.getId(), 1);
count++;
} else {
//推送失败
pushProcessMapper.updateFlagById(process.getId(), 2);
}
}
logger.info("线程{}推送成功{}条", threadNo, count);
return count;
}
}
}
JAVA使用多线程进行数据处理的更多相关文章
- Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
- java之多线程 二
线程的生命周期: 当线程被创建并被启动时,它既不是一启动就进入了执行状态,在线程的生命周期中,它要经过new(新建),就绪(Runnable),运行(Running),阻塞(Blocked),dead ...
- Java的多线程机制系列:(一)总述及基础概念
前言 这一系列多线程的文章,一方面是个人对Java现有的多线程机制的学习和记录,另一方面是希望能给不熟悉Java多线程机制.或有一定基础但理解还不够深的读者一个比较全面的介绍,旨在使读者对Java的多 ...
- Java Thread 多线程 介绍
1.线程概述 几乎所有的操作系统都支持同时运行多个任务,一个任务通常就是一个程序,每个运行中的程序就是一个进程. 当一个程序运行时,内部可能包含了多个顺序执行流,每个顺序执行流就是一个线程. 2.线程 ...
- Java:多线程<一>
程序运行时,其实是CPU在执行程序的进程,为了提高工作效率一个进程可以有多个线程. Java的多线程: 其实我们之前就见过Java的线程,main就是Java的一个线程,还有另一个条线程总是和main ...
- Java的多线程机制系列:(四)不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
- Java的多线程机制系列:(三)synchronized的同步原理
synchronized关键字是JDK5之实现锁(包括互斥性和可见性)的唯一途径(volatile关键字能保证可见性,但不能保证互斥性,详细参见后文关于vloatile的详述章节),其在字节码上编译为 ...
- Java基础——多线程
Java中多线程的应用是非常多的,我们在Java中又该如何去创建线程呢? http://www.jianshu.com/p/40d4c7aebd66 一.常用的有三种方法来创建多线程 新建一个类继承自 ...
- JAVA之多线程的创建
转载请注明源出处:http://www.cnblogs.com/lighten/p/5967853.html 1.概念 老调重弹,学习线程的时候总会牵扯到进程的概念,会对二者做一个区分.网上有较多的解 ...
随机推荐
- 洛谷 P4749 - [CERC2017]Kitchen Knobs(差分转换+dp,思维题)
题面传送门 一道挺有意思的思维题. 首先有一个 obvious 的结论,就是对于每个炉子,要么转到哪里都符合条件,要么存在唯一的最大值.对于转到哪儿都符合条件的炉子我们 duck 不必考虑它,故我们只 ...
- YAOI Round #1 (Div.2) 题解
总体来说很有一定区分度的(主要分为 4 题.2 题.1 题几档),ACM 赛制也挺有意思的,征求一下大家对这场比赛的意见吧,可以在这个帖子下回复,我都会看的. 简要题解:( A. 云之彼端,约定的地方 ...
- PPT——一个有情怀的免费PPT模板下载网站!“优品PPT”
http://www.ypppt.com/ PS:再推荐一款免费PPT下载网站 https://www.v5ppt.com/ppt-5-42-1.html
- 基于python win32setpixel api 实现计算机图形学相关操作
最近读研期间上了计算机可视化的课,老师也对计算机图形学的实现布置了相关的作业.虽然我没有系统地学过图形可视化的课,但是我之前逆向过一些游戏引擎,除了保护驱动之外,因为要做透视,接触过一些计算机图形学的 ...
- flink04 -----1 kafkaSource 2. kafkaSource的偏移量的存储位置 3 将kafka中的数据写入redis中去 4 将kafka中的数据写入mysql中去
1. kafkaSource 见官方文档 2. kafkaSource的偏移量的存储位置 默认存在kafka的特殊topic中,但也可以设置参数让其不存在kafka的特殊topic中 3 将k ...
- 大数据学习day23-----spark06--------1. Spark执行流程(知识补充:RDD的依赖关系)2. Repartition和coalesce算子的区别 3.触发多次actions时,速度不一样 4. RDD的深入理解(错误例子,RDD数据是如何获取的)5 购物的相关计算
1. Spark执行流程 知识补充:RDD的依赖关系 RDD的依赖关系分为两类:窄依赖(Narrow Dependency)和宽依赖(Shuffle Dependency) (1)窄依赖 窄依赖指的是 ...
- 大数据学习day17------第三阶段-----scala05------1.Akka RPC通信案例改造和部署在多台机器上 2. 柯里化方法 3. 隐式转换 4 scala的泛型
1.Akka RPC通信案例改造和部署在多台机器上 1.1 Akka RPC通信案例的改造(主要是把一些参数不写是) Master package com._51doit.akka.rpc impo ...
- VIM多标签页
:tabnew 增加一个标签 :tabc 关闭当前的tab :tabo 关闭所有其他的tab :tabp 或gT 前一个 :tabn 或gt 后一个 :tabs 显示 ...
- MyBatis Collection小记—— 关联查询、递归查询、多字段关联
经常会用到mybatis的Collection标签来做级联查询或递归查询,现通过一个伪例来简单的说明一下使用中的关键点: 首先先列出三个表,给出一个场景: 1,角色表 t_role( id,name ...
- 03-Collection用例管理及批量执行
当我们对一个或多个系统中的很多用例进行维护时,首先想到的就是对用例进行分类管理,同时还希望对这批用例做回归测试 .在postman也提供了这样一个功能,就是Collection .通过这个Collec ...