1.1需求

数据库300 万条用户数据 ,遍历获取所有用户, 各种组合关联, 获取到一个新的json ,存到redis 上。

1.2 难点

数据库比较多, 不可能单线程查询所有的数据到内存。

1.3解决办法

多线程读取, 生产者 每次获取200 条数据, 消费者去消费。(这里 主要是根据MySQL分页去获取下一个200 条数据)

1.4 代码

1.4.1 调用方法

    /**
* 线程启动
*/
public void update() {
//redis操作类
HashRedisUtil redisUtil= HashRedisUtil.getInstance();
//生产者消费者
ProducerConsumer pc = new ProducerConsumer();
//数据仓库
Storage s = pc.new Storage(); ExecutorService service = Executors.newCachedThreadPool();
//一个线程进行查询
Producer p = pc.new Producer(s,userMapper);
service.submit(p);
System.err.println("生产线程正在生产中。。。。。。。。。");
//是个线程进行修改
for(int i=0;i<10;i++){
System.err.println("消费线程"+i+"正在消费中。。。。。。。。。。");
service.submit(pc.new Consumer( redisUtil,userMapper,s));
} }

1.4.2 主要核心类

package com.ypp.thread;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.joda.time.LocalDateTime; import com.alibaba.fastjson.JSONObject;
import com.ypp.constants.Constants;
import com.ypp.mapper.UserMapper;
import com.ypp.model.User;
import com.ypp.model.UserAlis;
import com.ypp.model.UserBaseModel;
import com.ypp.model.UserVip;
import com.ypp.util.HashRedisUtil;
import com.ypp.util.JsonUtils;
import com.ypp.util.PHPSerializer; public class ProducerConsumer {
private static Logger logger = Logger.getLogger(ProducerConsumer.class);
//这个page 是核心, 全局变量, 当生产者生产一次 ,获取200 个用户, 会把这个page++, 下次获取就是后一个200 条用户了
private static Integer page = 0; //消费者

public class Consumer implements Runnable { private HashRedisUtil redisUtil;
private UserMapper userMapper;
private Storage s = null; public Consumer(HashRedisUtil redisUtil, UserMapper userMapper, Storage s) {
super();
this.redisUtil = redisUtil;
this.userMapper = userMapper;
this.s = s;
} public void run() {
try {
while (true) {
User users = s.pop(); long bbb = System.currentTimeMillis();
// 获取一个用户的粉丝列表 并存到redis
try {
fansUpdate(users.getToken(), users.getUserId(), redisUtil);
} catch (Exception e1) {
e1.printStackTrace();
}
// 获取一个用户的关注列表, 并存到redis
try {
followUpdate(users.getToken(), users.getUserId(), redisUtil);
} catch (Exception e) {
e.printStackTrace();
}
// 获取一个用户的黑名单, 并存到redis
try {
blackUpdate(users.getToken(), users.getUserId(), redisUtil);
} catch (Exception e) {
e.printStackTrace();
}
// 用户基本信息
try {
userbaseUpdate(users.getToken(), users.getUserId(), redisUtil);
} catch (Exception e) {
e.printStackTrace();
}
long ccc = System.currentTimeMillis();
System.out.println("用户:" + users.getToken() + " 全部总共耗时:" + (ccc - bbb) + "毫秒"); Thread.sleep(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
} } public List<User> getUserInfo(Integer iThread) {
return userMapper.findUserInfo((iThread - 1) * 200 + 1);
} /**
* 用户基本信息修改
*
* @param token
* @param myuserId
* @param redisUtil
* @throws Exception
*/
private void userbaseUpdate(String token, String myUserId, HashRedisUtil redisUtil) throws Exception { } /**
* 更新一个用户的黑名单(原来的token改成userID)
*
* @param token
* @param string
* @param redisUtil
* @throws Exception
*/
private void blackUpdate(String token, String myUserId, HashRedisUtil redisUtil) throws Exception { } /**
* 获取一个用户的关注
*
* @param token
* @param string
* @param redisUtil
* @throws Exception
*/
private void followUpdate(String token, String myUserId, HashRedisUtil redisUtil) throws Exception { } /**
* 获取一个用户的粉丝列表
*
* @param token
* @param userId
* @param redisUtil
* @throws Exception
*/
private void fansUpdate(String token, String myUserId, HashRedisUtil redisUtil) throws Exception { } //生产者
public class Producer implements Runnable {
private Storage s = null;
private UserMapper mapper ;
public Producer( Storage s, UserMapper mapper) { this.s = s;
this.mapper = mapper;
}
public void run() {
try { while (true) { System.err.println("当前分页是:"+page+"****************************************");
List<User> list= mapper.findUserInfo(page);
s.push(list);
page++;
}
} catch (InterruptedException e1) {
e1.printStackTrace();
} }
}

//数据仓库
public class Storage {
BlockingQueue<User> queues = new LinkedBlockingQueue<User>(200); /**
* 生产
*
* @param p
* 产品
* @throws InterruptedException
*/
public void push(List<User> p) throws InterruptedException {
for(User user:p){
queues.put(user);
}
} /**
* 消费
*
* @return 产品
* @throws InterruptedException
*/
public User pop() throws InterruptedException {
return queues.take();
}
} }

Java 线程池 +生产者消费者+MySQL读取300 万条数据的更多相关文章

  1. java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-【费元星Q9715234】

    java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-[费元星Q9715234] 说明如下,不懂的问题直接我[费元星Q9715234] 1.反射的意义在于不将xml tag ...

  2. 第23章 java线程通信——生产者/消费者模型案例

    第23章 java线程通信--生产者/消费者模型案例 1.案例: package com.rocco; /** * 生产者消费者问题,涉及到几个类 * 第一,这个问题本身就是一个类,即主类 * 第二, ...

  3. 复杂业务下向Mysql导入30万条数据代码优化的踩坑记录

    从毕业到现在第一次接触到超过30万条数据导入MySQL的场景(有点low),就是在顺丰公司接入我司EMM产品时需要将AD中的员工数据导入MySQL中,因此楼主负责的模块connector就派上了用场. ...

  4. 教你如何6秒钟往MySQL插入100万条数据!然后删库跑路!

    教你如何6秒钟往MySQL插入100万条数据!然后删库跑路! 由于我用的mysql 8版本,所以增加了Timezone,然后就可以了 前提是要自己建好库和表. 数据库test, 表user, 三个字段 ...

  5. java线程之生产者消费者

    看了毕向东老师的生产者消费者,就照着视频参考运行了一下,感觉还好 这个值得学习的是条理特别清晰: ProducterConsumerDemo.java中,一个资源类Resources,生产者消费者都可 ...

  6. 线程锁,threadinglocal,线程池,生产者消费者模型

    1.线程锁 1.锁Lock(只能锁一次) import threading import time v = [] lock = threading.Lock() def func(arg): lock ...

  7. Java线程通信-生产者消费者问题

    线程通信示例——生产者消费者问题 这类问题描述了一种情况,假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中的产品取走消费.假设仓库中没有产品,则生产者可以将 产品放入仓库,有 ...

  8. mysql生成20万条数据(连表插入)

    创建一个存储过程 DELIMITER $$ -- 设置定界符为$$,与';'意思相同,防止相同符号产生冲突 USE `yunkc_base1`$$ -- 使用数据库 DROP PROCEDURE IF ...

  9. mysql插入一万条数据

    定义一个存储过程 mysql> delimiter $$ mysql> create procedure ptest()    -> begin    -> declare p ...

随机推荐

  1. Mybatis笔记 - 原始Dao开发方法

    使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper接口开发方法.原始Dao的开发方式是基于入门程序的基础上,对 控制程序 进行分层开发,程序员需要 编写 Dao接口 和 ...

  2. YARN 原理简介

    YARN 组件 参考:Spark on Yarn | Spark,从入门到精通 YARN 采用 Master/Slave结构 ,包含ResourceManager 和 NodeManager Reso ...

  3. Mysql优化系列之查询优化干货1

    从这一篇开始,准备总结一些直接受用的sql语句优化,写sql是第二要紧的,第一要紧的,是会分析怎么查最快, 因为当你写过很多sql后,查询出结果已经不是目标,快,才是目标.另外,通过测试和比较的结果才 ...

  4. 2_2.springboot2.x配置之自动配置原理

    前言 SpringBoot 自动配置原理: 本文主要分为三大部分: SpringBoot 源码常用注解 SpringBoot 启动过程 SpringBoot 自动配置原理 1. SpringBoot ...

  5. JS中鲜为人知的问题: [] == ![]结果为true,而 {} == !{}却为false

    console.log( [] == ![] ) // true console.log( {} == !{} ) // false 在比较字符串.数值和布尔值的相等性时,问题还比较简单.但在涉及到对 ...

  6. CSS——div内文字的溢出部分用省略号显示

    使得div内文字的溢出部分用省略号显示,可归纳为两种解决办法,一种方法是用CSS解决,另一种方法是js解决. 一.通过CSS控制显示 div内显示一行,超出部分用省略号显示 div内显示多行,超出部分 ...

  7. Spark历险记之编译和远程任务提交

    Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架.Spark在2013年6月进入Apach ...

  8. Apache Pig和Solr问题笔记(一)

    记录下最近两天散仙在工作中遇到的有关Pig0.12.0和Solr4.10.2一些问题,总共有3个,如下: (1)问题一: 如何Pig中使用ASCII和十六进制(hexadecimal)的分隔符进行加载 ...

  9. 移植 TinyLogin

    下载 从 http://tinylogin.busybox.net/downloads/tinylogin­1.4.tar.bz2下载 tinylogin­1.4 到/tmp 目录当中,并解压. 修改 ...

  10. git安装与上传

    git安装与上传 上一篇 / 下一篇  2017-03-10 10:09:42 / 个人分类:代码管理工具 查看( 63 ) / 评论( 0 ) / 评分( 0 / 0 ) 1.安装Git-2.11. ...