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. iOS开发线程之NSThread

    1.初始化 - (instancetype)init API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0)) NS_DESIGNAT ...

  2. Mysql优化系列之表设计规范和优化

    一.范式 如果详细的讲范式,要写大大大篇文章来讲,这里假设大家知道一些基本的范式规则,我用简洁的语句和例子说明 第一范式:列不可再分,譬如地址字段,可以再细分为省市区门牌号等等(其实还是看需求怎么整) ...

  3. django零散知识点

    后端将对象以对象形式传到前端: from django.core.serializers import serialize def xxx(reqeust): project_list = model ...

  4. springboot整合mybatis进行跨库查询

    业务场景: 当一个公司大了之后就会将各种业务进行分开,最简单的就是例如:公司的机构表,那么就会将他们分成开来,那么就会在一个实例中, 如果要获取相关信息就会去关联这张表进行关联查询 从而导致了跨库关联 ...

  5. iOS逆向系列-Reveal

    概述 Reveal是一款调试iOS程序UI界面的神器. 官网地址:https://revealall.com 下载:https://revealapp.com/download/ 建议下载Reveal ...

  6. SpringCloud学习笔记《---04 Hystrix---》基础篇

  7. [转]gnome环境中将家目录下预设的文件夹由中文名称改为英文名称

    参考文章:gnome环境中将家目录下预设的文件夹由中文名称改为英文名称 打开终端 1 修改语言环境为英文 export LANG=en_US 如果想修改语言环境为日语,可执行 export LANG= ...

  8. shell学习笔记2: shell中的四则运算符

    shell中的四则运算符 n1,n2 :常量数字 char:运算符号 加,减,乘,除,取余(+,-,*,/,%) $a,$b:变量a,变量b 方法1 数字与符号之间需要有空格 不支持小数 expr n ...

  9. Spring简洁总结

    Spring简洁总结  要的对象不是自己建的,而是IOC容器(XML文件)给的,我们通过getbean来调用. 依赖注入的话就是对象(bean)的成员的赋值不是我们手动完成,而是容器(XML文件)给我 ...

  10. varStatus实现<c:forEach获取元素的下标 集合长度

    有时候需要获取元素的下标,来实现一个编号的效果 那么使用 varStatus可以实现 代码 效果 如果需要把序号倒着数 那就用集合的长度减去当前下标 首先引入 <%@ taglib prefix ...