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使用多线程进行数据处理的更多相关文章

  1. Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)

    一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...

  2. java之多线程 二

    线程的生命周期: 当线程被创建并被启动时,它既不是一启动就进入了执行状态,在线程的生命周期中,它要经过new(新建),就绪(Runnable),运行(Running),阻塞(Blocked),dead ...

  3. Java的多线程机制系列:(一)总述及基础概念

    前言 这一系列多线程的文章,一方面是个人对Java现有的多线程机制的学习和记录,另一方面是希望能给不熟悉Java多线程机制.或有一定基础但理解还不够深的读者一个比较全面的介绍,旨在使读者对Java的多 ...

  4. Java Thread 多线程 介绍

    1.线程概述 几乎所有的操作系统都支持同时运行多个任务,一个任务通常就是一个程序,每个运行中的程序就是一个进程. 当一个程序运行时,内部可能包含了多个顺序执行流,每个顺序执行流就是一个线程. 2.线程 ...

  5. Java:多线程<一>

    程序运行时,其实是CPU在执行程序的进程,为了提高工作效率一个进程可以有多个线程. Java的多线程: 其实我们之前就见过Java的线程,main就是Java的一个线程,还有另一个条线程总是和main ...

  6. Java的多线程机制系列:(四)不得不提的volatile及指令重排序(happen-before)

    一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...

  7. Java的多线程机制系列:(三)synchronized的同步原理

    synchronized关键字是JDK5之实现锁(包括互斥性和可见性)的唯一途径(volatile关键字能保证可见性,但不能保证互斥性,详细参见后文关于vloatile的详述章节),其在字节码上编译为 ...

  8. Java基础——多线程

    Java中多线程的应用是非常多的,我们在Java中又该如何去创建线程呢? http://www.jianshu.com/p/40d4c7aebd66 一.常用的有三种方法来创建多线程 新建一个类继承自 ...

  9. JAVA之多线程的创建

    转载请注明源出处:http://www.cnblogs.com/lighten/p/5967853.html 1.概念 老调重弹,学习线程的时候总会牵扯到进程的概念,会对二者做一个区分.网上有较多的解 ...

随机推荐

  1. Pólya 定理学习笔记

    在介绍\(Polya\) 定理前,先来介绍一下群论(大概了解一下就好): 群是满足下列要求的集合: 封闭性:即有一个操作使对于这个集合中每个元素操作完都使这个集合中的元素 结合律:即对于上面那个操作有 ...

  2. 洛谷 P6783 - [Ynoi2008] rrusq(KDT+势能均摊+根号平衡)

    洛谷题面传送门 首先显然原问题严格强于区间数颜色,因此考虑将询问离线下来然后用某些根号级别复杂度的数据结构.按照数颜色题目的套路,我们肯定要对于每种颜色维护一个前驱 \(pre\),那么答案可写作 \ ...

  3. R语言中的read.table()

    参考资料:http://www.cnblogs.com/xianghang123/archive/2012/06/06/2538274.html read.table(file, header = F ...

  4. rust shadow

    1 fn main() { 2 let mut demo = 12; 3 println!("{}",demo); 4 demo = 21; // 值可变,数据类型不可变 5 pr ...

  5. 56-Remove Linked List Elements

    Remove Linked List Elements My Submissions QuestionEditorial Solution Total Accepted: 61924 Total Su ...

  6. 每日自动健康打卡(Python+腾讯云服务器)

    每日自动健康打卡(Python+腾讯云服务器) 1.配置需要 python3.7,Chrome或者Edeg浏览器,Chrome驱动或者Edge驱动 #需要配置selenium库,baidu-aip库, ...

  7. SpringBoot整合Shiro 一:搭建环境

    Java项目的安全框架一般使用 shiro 与 spring security 具体怎么选择可以参考文章:安全框架 Shiro 和 Spring Security 如何选择 我这里选择使用Shiro ...

  8. UE4类型数据自动注册

    Version:4.26.2 UE4 C++工程名:MyProject 在<宏GENERATED_BODY做了什么?>中,简单分析了GENERATED_BODY宏给一个简单的.继承自UOb ...

  9. 源码分析-Producer

    消息生产者的代码都在client模块中,相对于RocketMQ来讲,消息生产者就是客户端,也是消息的提供者. 方法和属性 主要方法介绍 //创建主题 void createTopic(final St ...

  10. 淘宝、网易移动端 px 转换 rem 原理,Vue-cli 实现 px 转换 rem

       在过去的一段时间里面一直在使用Vue配合 lib-flexible和px2rem-loader配合做移动端的网页适配.秉着求知的思想,今天决定对他的原理进行分析.目前网上比较主流使用的就是淘宝方 ...