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.概念 老调重弹,学习线程的时候总会牵扯到进程的概念,会对二者做一个区分.网上有较多的解 ...
随机推荐
- Codeforces 1137F - Matches Are Not a Child's Play(LCT)
Codeforces 题面传送门 & 洛谷题面传送门 考虑将一个点 \(x\) 的编号变为当前所有点编号最大值 \(+1\) 会对每个点的删除时间产生怎么样的影响.由于编号最大的点肯定是最后一 ...
- Atcoder Grand Contest 005 E - Sugigma: The Showdown(思维题)
洛谷题面传送门 & Atcoder 题面传送门 记先手移动棋子的树为红树,后手移动棋子的树为蓝树. 首先考虑一个性质,就是如果与当前红色棋子所在的点相连的边中存在一条边,满足这条边的两个端点在 ...
- CF1202E You Are Given Some Strings...
题目传送门. 题意简述:给出 \(t\) 与 \(s_{1,2,\cdots,n}\).求对于所有 \(i,j\in[1,n]\),\(s_i+s_j\) 在 \(t\) 中出现次数之和. 如果只有 ...
- centos 安装reids
1.安装tcl支持 yum install tcl 2.安装redis我们以最新的2.8.9为例 $ wget http://download.redis.io/releases/redis-2.8. ...
- Hi3516开发笔记(六):通过HiTools使用USB/串口将uboot、kernel、roofts和userdata按照分区表烧写镜像
若该文为原创文章,转载请注明原文出处本文章博客地址:https://hpzwl.blog.csdn.net/article/details/121706033红胖子(红模仿)的博文大全:开发技术集合( ...
- C++ 中的多重继承的问题
如何正确使用C++多重继承 BY R12F · PUBLISHED 2011年06月17日 · UPDATED 2012年03月11日 原创文章,转载请注明:转载自Soul Apogee本文链接地 ...
- Factorization
Factorization or factoring consists of writing a number or another mathematical object as a product ...
- iOS11&IPhoneX适配
1.在iOS 11中,会默认开启获取的一个估算值来获取一个大体的空间大小,导致不能正常显示,可以选择关闭.目前尝试在delegate中处理不能很好的解决,不过可以直接设置: Swift if #ava ...
- binlog2sql 解析日志失败 UnicodeDecodeError: 'utf-8' codec can't decode byte 0xba in position 0: invalid start byte
python35 ./binlog2sql.py -h... -P... -u... -p... -B --start-file="mysql-bin.091940" --star ...
- go goroutines 使用小结
go +方法 就实现了一个并发,但由于环境不同,需要对并发的个数进行限制,限制同一时刻并发的个数,后面称此为"并发限流". 为什么要并发限流? 虽然GO M+P+G的方式号称可以轻 ...