当前位置: 首页 > 编程日记 > 正文

java多线程查询_利用Java函数式接口处理多线程查询

Java函数式接口

有且只有一个抽象方法的接口被称为函数式接口.

@FunctionalInterface注解: 该注解可用于一个接口的定义上, 一旦使用该注解来定义接口, 编译器将会强制检查该接口是否确实有且仅有一个抽象方法, 否则将会报错.该注解不是必须的, 只要符合函数式接口的定义,那么这个接口就是函数式接口.

1. Java中函数式接口应用

Runnable 接口

@FunctionalInterface

public interface Runnable {

// 仅有一个run方法

public abstract void run();

}

Executor接口定义

public interface Executor {

// 接收一个Runnable对象

void execute(Runnable command);

}

线程池中使用submit()方法提交任务

public class ThreadPoolDemo {

private final static ThreadPoolExecutor EXECUTOR =

new ThreadPoolExecutor(8, 8, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1000000), new ThreadPoolExecutor.AbortPolicy());

public static void main(String[] args) {

for (int i = 1; i <= 100; i ++){

// () -> System.out.println("hello world") 即表示一个Runnable对象, Java8之前为匿名内部类

EXECUTOR.execute(() -> System.out.println("hello world"));

// EXECUTOR.execute(new Runnable() {

// @Override

// public void run() {

// System.out.println("hello world");

// }

// });

}

}

}

2. 自定义函数接口

public interface ExecuteService {

void execute(String message);

}

public class Demo {

public void execute(ExecuteService service, String message){

service.execute(message);

}

public static void main(String[] args) {

Demo demo = new Demo();

String message = "你好";

demo.execute(message1 -> System.out.println(message1), message);

}

}

使用场景

在实际开发中, 经常会遇到针对多个业务过程统计表的统计查询.

比如:

指定一个时间段, 查询该时间段的统计数据

指定一个时间段, 查询该时间段的统计数据, 并根据时间分组(比如按每天)

在表的数据量较小的情况下, 一般可以直接进行统计.

SELECT COUNT(*) FROM 表 WHERE create_time >= #{T1} AND create_time <= #{T2};

如果表的数据量很大的情况下, 则COUNT的数据量可能很大, 导致SQL执行慢.

遇到这种情况一般先会针对SQL进行优化, 比如走索引. 如果走索引还是因为数据量大而导致查询慢,那么就需要将查询时间进行拆分, 拆分成一天一天查询.并开通多线程进行查询, 以多次IO数据库换取减少慢SQL操作.

SELECT COUNT(*) FROM 表 WHERE create_time = #{T};

实际场景应用

定义函数式接口

public interface OldFlowTrendCallback {

/**

* 查询数据趋势

* @param param

* @return

*/

List execute(OldFlowDashBoardParamDTO param);

}

定义针对批量多线程查询的接口方法

@Service

@Slf4j

public class OldFlowBatchSelectExecutor extends BaseBatchSelect {

/** 业务线程池*/

@Autowired

private ThreadPoolExecutor statThreadPoolExecutor;

public List execute(OldFlowTrendCallback callback, OldFlowDashBoardParamDTO dto){

Date startTime = dto.getStartTime();

Date endTime = dto.getEndTime();

// 判断是否查询的时间段是同一天, 如果是, 则直接执行

if (DateUtil.isTheSameDay(startTime, endTime)) {

setAssignDate(dto);

return callback.execute(dto);

}

// 创建队列, 接收异步线程执行结果

BlockingQueue>> queue = new LinkedBlockingQueue<>();

// 如果查询时间段为一个时间段, 那么则拆分成一天一天的查询处理

while (startTime.getTime() < endTime.getTime()) {

OldFlowDashBoardParamDTO dayParam = VOUtil.from(dto, OldFlowDashBoardParamDTO.class);

dayParam.setStartTime(startTime);

dayParam.setEndTime(startTime);

setAssignDate(dayParam);

// 通过线程池异步执行任务, 返回Futrue

Future> future = statThreadPoolExecutor.submit(() -> callback.execute(dayParam));

queue.add(future);

startTime = DateUtil.getNextDateFirst(startTime);

}

// 封装返回接口, 主要是使用Futrure接口get()方法, 阻塞获取异步线程执行的结果

return packBatchSelectResult(queue);

}

private void setAssignDate(OldFlowDashBoardParamDTO dto) {

Date startAssignDate = DateUtil.addDateDays(dto.getStartTime(), - dto.getAssignDateType());

Date endAssignDate = DateUtil.getYestodayFirst(dto.getStartTime());

dto.setStartAssignDate(startAssignDate);

dto.setEndAssignDate(endAssignDate);

}

}

业务方法

public List listOldFlowGroupByStatDate(OldFlowDashBoardParamDTO dto) {

// 通过OldFlowBatchSelectExecutor 统一处理拆分多线程查询

// (dayParam) -> effectiveFollowingMapper.listOldFlow(dayParam)): 即是OldFlowTrendCallback接口实现

return oldFlowBatchSelectExecutor.execute(((OldFlowTrendCallback) (dayParam) -> effectiveFollowingMapper.listOldFlow(dayParam)), dto);

}

相关文章:

奇妙的算法之LCS妙解

LCS算法妙解 LCS问题简述&#xff1a;最长公共子序列 一个数列 S&#xff0c;如果分别是两个或多个已知数列的子序列&#xff0c;且是所有符合此条件序列中最长的&#xff0c;则S 称为已知序列的最长公共子序列。 LCS问题的分支&#xff1a;最长公共子串与最长公共子序列 子串&…

关于PreferenceActivity的使用和一些问题的解决(自己定义Title和取值)

android的Setting往往用PreferenceActivity来写的 我们在建立layout文件: <PreferenceScreen xmlns:android"http://schemas.android.com/apk/res/android"> <PreferenceCategory android:title"常规设置" android:key"set_local">&…

python学习-25 函数递归

递归 例如&#xff1a; def abc(n):print(n)if int(n/2) 0:return nreturn abc(int(n/2))abc(10) 运行结果&#xff1a; 10 5 2 1Process finished with exit code 0 2.小程序实例 import time people_list [小明,小红,小刚,小王,小青]def ask(people_list):if len(people_li…

二维指针删除单向链表

Linus slashdot: https://meta.slashdot.org/story/12/10/11/0030249 原文&#xff1a; https://coolshell.cn/articles/8990.html Linus大婶在slashdot上回答一些编程爱好者的提问&#xff0c;其中一个人问他什么样的代码是他所喜好的&#xff0c;大婶表述了自己一些观点…

对比java_java集合对比

list与Set、Map区别及适用场景1、List,Set都是继承自Collection接口&#xff0c;Map则不是2、List特点&#xff1a;元素有放入顺序&#xff0c;元素可重复 &#xff0c;Set特点&#xff1a;元素无放入顺序&#xff0c;元素不可重复&#xff0c;重复元素会覆盖掉&#xff0c;(注…

.ARM.exidx

简介&#xff1a; .ARM.exidx is the section containing information for unwinding the stack. If your C program has functions that print out a stack backtrace, the functions will likely depend on this section being present. 相关的编译选项 -funwind-tables 二问…

Oracle VM VirtualBox安裝Windows 2000失败

问题&#xff1a;VirtualBox下安装Windows2000&#xff0c;设置网络后进入最后一步&#xff0c;复制组件……然后就是重启&#xff1b;再试还是重启&#xff01;解决&#xff1a;在Oracle网站上查了一下资料&#xff1a;http://www.virtualbox.org/manual/ch12.html#idp1278616…

用户/目录操作

用户操作 useradd/adduser 创建用户 passwd 修改用户密码 userdel 删除用户 usermod 修改用户信息 -g<群组> 修改用户所属群组 -G<群组> 修改用户所属的附加群组 -l<帐户名> 修改账户名称 -u 修改用户ID -L锁定用户密码 -U 解除密码锁定 adduser -u用…

linux内核 -内存管理模块概图

1.从进程(task)的角度来看内存管理 每个进程对应一个task_struct;每个task_struct 里面包含指向mm_struct 的指针mm, mm_struct 里面的主要成员&#xff1a; a. 指向vma链表的头指针&#xff1a;mmap b. 指向vma红黑树的根节点: mm_rb c. 指向进程列表的指针pgb;vma(vm_are…

求一个字符串中连续出现的次数最多的子串

求一个字符串中连续出现的次数最多的子串。例如字符串“abababc”,最多连续出现的为ab&#xff0c;连续出现三次。要和求一个字符串中的最长重复子串区分开来&#xff0c;还是上面的字符串&#xff0c;那么最长的重复子串为abab。两个题目的解法有些类似&#xff0c;都用到了后…

java ftp 判断文件是否存在_FTP判断文件是否存在

FTP Client使用的是Apache Commons Net 3.3/*** 检查FTP上指定文件是否存在* param remoteFilePartNameList 文件路径* throws BusinessException* throws IOException*/private void checkFtpFileExist(List remoteFilePartNameList) throws BusinessException, IOException {…

软件定义光网络-SDON

为什么80%的码农都做不了架构师&#xff1f;>>> 软件定义光网络-SDON 随着宽带业务与应用的持续增长&#xff0c;光网络面临着新的发展机遇与技术挑战。作为当前业界研究热点之一&#xff0c;SDON聚焦于将软件定义技术融入光网络的综合解决方案&#xff0c;其关键技…

记录一次爬取某昵称网站的爬虫

同学跑去实习了...然后工作的时候要她用python写一个爬虫&#xff0c;爬取一万个可以用的用户昵称。&#xff08;为什么他们都能找到工作啊QAQ&#xff09; 然后&#xff0c;她找到了我...然后在我动笔的时候&#xff0c;发现之前写过的爬虫基本上忘完了...无奈下只好对着以前…

《LINUX3.0内核源代码分析》第一章:内存寻址

https://blog.csdn.net/ekenlinbing/article/details/7613334 摘要&#xff1a;本章主要介绍了LINUX3.0内存寻址方面的内容&#xff0c;重点对follow_page函数进行注释&#xff0c;以帮助读者大致了解ARM A9的页表组织。 读者需要理解一些基本概念&#xff1a;虚拟地址、物理地…

java integer int 比较_java Integer和int之间的比较问题是什么?

展开全部java Integer和int之间e68a84e8a2ad3231313335323631343130323136353331333365633864的比较问题。求解释public static void main(String[] args) { // TODO Auto-generated method stub Integer a new Integer(1); Integer b new Integer(1); int c1; Integer e 1;…

Oracle 12C -- 基于sequence的列的默认值

12C支持先创建一个sequence&#xff0c;然后再将该sequence指定为某个列的值的默认表达式。 和"identity column"具有以下不同点&#xff1a; 对列的个数没有限制 sequence必须在列定义之前定义 如果删除了sequence&#xff0c;会导致后面的insert报错 表的owner&…

Python的XML-RPC学习

编写客户端提交数据到服务器处理是程序员最常碰到的几个问题之一。各种不同的语言对此都有相应的解决方案。比如Unix下&#xff0c;C程序员们可以用SUNRPC&#xff0c;Java程序员则使用RMI来处理。大多数语言还都可以使用Web Service或者ICE。它们的使用方法类似&#xff0c;编…

Anaconda安装,jupyter notebook 使用说明

conda install pandas---安装pandas包 conda remove package_names conda update package_names conda list ---列出该环境下安装的package conda install nb_conda --------安装nb_conda用于notebook自动关联nb_conda的环境 conda create -n env_name package_name -------…

ARM32页表-虚拟地址到物理地址的转换

ARM32的页表 页表就是用于将虚拟地址转换为物理地址的转换关系表。访问虚拟地址时&#xff0c;计算机通过页表找到对应的实际物理地址访问。 我们在上一节介绍了内存管理模块概图, 怎么完成从pgd 到 page的转化呢&#xff1f; linux 内核code是通过follow_page来完成的…

java 重载 参数子类_java - Java中带有子类参数的函数重载 - 堆栈内存溢出

这个问题已经在这里有了答案&#xff1a;我有一个扩展了另一个类的类(在这种情况下&#xff0c;这是一个例外)&#xff1a;public class NewTypeException extends Exception {private String exceptionField;public String getExceptionField() {return exceptionField;}publi…

Caused by: java.sql.BatchUpdateException

Caused by: java.sql.BatchUpdateException: Table (%s) has been dropped, altered or renamed.解决方法重启项目转载于:https://www.cnblogs.com/mySummer/p/4723561.html

do{ ...}while(0)应用技巧

辅助定义复杂的宏example: #define A(args) do { a(args); b() } while(0);如果定义#define A(args) a(args);b();if(i > 0) A(i) if(i > 0 )do { a(2);b();} while(0) 或者while(1)a(args);b(); 这不是我们想要的&#xff0c;因为第二个b();不会被执行。代替g…

Idea--使用Idea调试设置

参考 https://blog.csdn.net/yyjava/article/details/81453748 关闭一些Idea默认设置&#xff0c;否则懵逼到爆炸.. 1.关闭集合类视图 2.关闭watch视窗默认调用toString&#xff08;真的很懵逼&#xff01;&#xff01;&#xff09; 转载于:https://www.cnblogs.com/microcat/p…

基于i2c子系统的驱动分析

https://blog.csdn.net/qq_28992301/article/details/52467766

creo JAVA_Creo 4.0二次开发工具框架搭建

一、新建MFC DLL工程二、配置项目属性附加依赖项中输入&#xff1a;netapi32.lib;psapi.lib;mpr.lib;wsock32.lib;protk_dll_NU.lib;protk_dllmd_NU.lib;protkmd_NU.lib;protoolkit_NU.lib;pt_asynchronous.lib;ptasyncmd.lib;ucore.lib;udata.lib;尝试编译工程&#xff0c;如果…

html5 FileReader初识

使用html5的FileReader可以实现多媒体文件的预览功能&#xff0c;代码如下&#xff1a; <html> <head> <script type"text/javascript"> var fileReader new FileReader(); fileReader.onload function(event) {document.getElementById(image).…

puppet aix之自动化用户管理

一、 用户组的管理 (一) Puppet组管理特性 1. manages_aix_lam用来管理AIX的LAM(Loadable Authentication Module)系统。 2. manages_members对于目录服务是组属性成员&#xff0c;而不是用户。 3. system_groups用来允许你创建比较小GID的系统组&#xff0c;一般小…

C# 文件操作

C# 文件操作文件操作: 检查 创建 读取 写入 修改 删除目录操作: 检查 创建 读取 写入 修改 删除文件操作 若要执行此操作...请参阅本主题中的示例...创建文本文件向文件写入文本写入文本文件向文件写入文本读取文本文件从文件读取文本向文件中追加文本File.AppendText FileInfo…

一种内存池管理技术

本文介绍一种内存池管理技术。 在m公司工作了4年多&#xff0c;一直负责内存池模块问题的处理&#xff0c;比如内存越界&#xff0c;data abort 系统异常的处理&#xff0c;本文加以总结&#xff0c;以便后续参考。 读本文之前&#xff0c;先有个约定&#xff0c;本文中提到的p…

企业支付宝账号开发接口实现

转载自&#xff1a;http://my.oschina.net/xshuai/blog/313809 关于即时到账的开发。审核通过。简单测试如下。 希望看的可以收藏或者赞一下哦。 1:拥有自己的支付宝企业账号。去产品商店选择适合自己的方案。并签约合同。 2:选择合适的商家收款产品并去签约。填写相应的信息 3…