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. 响应式编程(Reactive Programming)(Rx)介绍

    很明显你是有兴趣学习这种被称作响应式编程的新技术才来看这篇文章的. 学习响应式编程是很困难的一个过程,特别是在缺乏优秀资料的前提下.刚开始学习时,我试过去找一些教程,并找到了为数不多的实用教程,但是它 ...

  2. Celery - 异步任务 , 定时任务 , 周期任务

    1.什么是Celery?Celery 是芹菜Celery 是基于Python实现的模块, 用于执行异步定时周期任务的其结构的组成是由    1.用户任务 app    2.管道 broker 用于存储 ...

  3. 《DSP using MATLAB》Problem 8.36

    上代码: function [wpLP, wsLP, alpha] = lp2lpfre(wplp, wslp) % Band-edge frequency conversion from lowpa ...

  4. Wireless Password HDU - 2825

    题意: 给出m个模式串,要求构造一长度为n的文本串,至少包括k种模式串,求有多少种可能的模式串. k<=10  然后可以想到状压 一个文本串,k种模式串,很容易想到AC自动机. 把所有的模式串放 ...

  5. 2018-8-10-win10-uwp-验证输入-自定义用户控件

    title author date CreateTime categories win10 uwp 验证输入 自定义用户控件 lindexi 2018-08-10 19:16:51 +0800 201 ...

  6. JavaScript数组的2种定义方式

    JavaScript中没有数组类型,JavaScript中数组是以内置对象的形式存在的. 数组是存储多个值的集合(仓库). JS中定义数组的2种方式: 1.使用new Array()构造函数定义数组 ...

  7. It's a Mod, Mod, Mod, Mod World (类欧几里得模板题

    https://vjudge.net/contest/317000#problem/F #include <iostream> #include <cstdio> #inclu ...

  8. odoo 下 get_object_reference 函数

    get_object_reference是 ir.model.data 模块中下的一个函数 该函数通过调用ir.model.data 模块中另外一个函数 xmlid_lookup 返回结果 def g ...

  9. 修改Apache的默认站点目录的方法,需要的朋友可以参考下

    由于博客系统崩了,所以要考虑重新建立博客系统,首先遇到的一个问题就是原来的博客系统是安装一个独立的磁盘上面的(http://m.0834jl.com)不是安装在系统盘上面的,然而一般在linux下面安 ...

  10. 【JEECG-Boot 技术文档】新手入门教程

    Jeecg-Boot入门教程必看(新手学习) 1.开发环境搭建 http://jeecg-boot.mydoc.io/?t=345670 开发工具 :https://pan.baidu.com/sha ...