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. VS2010-MFC(MFC常用类:MFC异常处理)

    转自:http://www.jizhuomi.com/software/236.html 上一节讲了CFile文件操作类,本节主要来说说MFC异常处理. 在鸡啄米C++编程入门系列的最后一节鸡啄米:C ...

  2. 线程池_ThreadPool

    using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; ...

  3. HDU-6375-度度熊学队列-双端队列deque/list

    度度熊正在学习双端队列,他对其翻转和合并产生了很大的兴趣. 初始时有 NN 个空的双端队列(编号为 11 到 NN ),你要支持度度熊的 QQ 次操作. ①11 uu ww valval 在编号为 u ...

  4. Facebook分布式框架—Thrift介绍。

    Thrift介绍 Thrift是一个分布式RPC框架,用来进行可扩展且跨语言的服务的开发.它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, ...

  5. c#窗体开发

    奇: 常用控件的使用(期间参杂着VS快捷键/常用设置) 快捷键:引用命名空间:shift+alt+F10 断点:F9 调试:F5 逐句调试(每行代码一次跳转):F11 逐过程调试:F10 重构提取方法 ...

  6. 浅谈web应用的高可用

    1.熟悉几个组件 1.1.apache     —— 它是Apache软件基金会的一个开放源代码的跨平台的网页服务器,属于老牌的web服务器了,支持基于Ip或者域名的虚拟主机,支持代理服务器,支持安全 ...

  7. xcart小数点位数

    xcart小数点的位数默认是2位,有时候需要根据需要更改位数:一开始以为把数据库中的数据类型的位数更改过后,就能生效,结果发现xcart在程序中作了限制,只能是2位.那么只能通过更改程序的方式来更改了 ...

  8. UVA - 374

    https://vjudge.net/problem/19685/origin 费马小定理优化快速幂 因为加了费马小定理优化,小心2 2 2这种情况,会出现0 0 2,也就是0的0次方,实际答案为0 ...

  9. thinkphp 快捷查询

    快捷查询方式是一种多字段查询的简化写法,可以进一步简化查询条件的写法,在多个字段之间用|分割表示OR查询,用&分割表示AND查询,可以实现下面的查询,例如: 大理石平台价格 一.不同字段相同的 ...

  10. 18多校8th

    a-容斥原理(带限制的不定方程) #include<bits/stdc++.h> using namespace std; #define mod 998244353 #define ll ...