大数据和高并发一直是Java中的核心技术,下面我将从几个方面来学习之。
第一个问题
单线程的方式首先被排除,因为太消耗内存和资源。多线程如何?同样的消耗资源,但是如何用到线程池可以有效的避免这些问题,然而,在springboot中,我更喜欢用异步的方式去实现这个效果。
如何大批量的插入数据,比如如何快速的插入100万条数据?
@Service
@Log
public class TestThread {
@Autowired
public JdbcTemplate jdbcTemplate;
@SuppressWarnings("deprecation")
@Async
public void run() {
while (true) {
testThread();
}
}
public void testThread() {
String sql = "INSERT INTO s_order_label_status(customer_id, created_time, order_id, tracking_no, url, _token_id, count_track, last_track_time, label_status, remark, code) values";
for (long i = 0; i < 100; i++) {
sql += "(13105925, "+System.currentTimeMillis()+", 12912930979, 'DM"+System.currentTimeMillis()+"YQ', '', 1477, 0, "+(System.currentTimeMillis()-10*20*1000)+", 0, NULL, ''),";
}
sql =sql.substring(0, sql.lastIndexOf(","));
jdbcTemplate.execute(sql);
}
}
注意:在生产环境中,一般是通过消息队列进行数据的处理,建议在run方法中用redis或者其他消息中间件进行数据的处理
public void run() {
while (true) {
redisTemplate.get("*");
}
}
另外注意这个的TestThread 并没有实现多线程,它是通过注解@Async 来实现的,但是这个注解是需要配置的,具体的配置如下:
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数
executor.setCorePoolSize(6);
// 设置最大线程数
executor.setMaxPoolSize(10);
// 设置队列容量
executor.setQueueCapacity(20);
// 设置线程活跃时间(秒)
executor.setKeepAliveSeconds(60);
// 设置默认线程名称
executor.setThreadNamePrefix("线程序号-");
// 设置拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
}
配置完之后,用注入的方式进行调用,而不能用new TestThread 的方式,否则jdbcTemplate 会报空指针异常。
@Autowired
private TestThread testThread;
@RequestMapping(value = "/test8")
@ResponseBody
public void test8(){
for (int i = 0; i < 3; i++) {
testThread.run();
}
}
经过测试,发现随着i 的数量越大,插入数据的速度越快,100万条数据几分钟就可以插入完成,比单线程快的不止几百倍。
for (long i = 0; i < 100; i++) {
}