經(jīng)過多線程的學(xué)習(xí)和實踐 總結(jié)了兩種多線程查表方法?
兩種方法都經(jīng)過我的封裝 某表使用時 server層加上方法sql即可
查詢流程:
1 count全表條數(shù)
2 通過總條數(shù) 將全表數(shù)據(jù)分為10份
3 開辟10個線程查詢limit語句(線程數(shù)可自定義)
以下方法均以mysql數(shù)據(jù)庫測試 其他庫同理
目錄
一?線程池方法
二 @Async注解方法
一?線程池方法
controller層
int totalNum = testService.countNum(new testTable());
//重寫多線程中引用的方法
List<T> threadHandle = ThreadPoolUtils.threadPool(totalNum, new ThreadTableDataQuery() {
@Override
public List<T> selectTableData(Integer page, Integer limit) throws Exception {
return testService.selectTableData(page, limit);
}
});
//lambda表達(dá)式寫法
//List<T> threadHandle = ThreadPoolUtils.threadPool(totalNum, (page, limit) -> testService.selectTableData(page, limit));
//轉(zhuǎn)換為list對象
List<TestTable> test= JSON.parseArray(JSON.toJSONString(threadHandle), testTable.class);
當(dāng)數(shù)據(jù)量多時 JSON.parseArray和JSON.toString轉(zhuǎn)換方法較慢
下篇文章我再介紹下泛型List轉(zhuǎn)List對象(Json轉(zhuǎn)換工具類)https://blog.csdn.net/weixin_56567361/article/details/128116842
java反射方式和強轉(zhuǎn)方法比阿里巴巴fastJson方式快了40多倍
ThreadPoolUtils
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;
/**
* 多線程查全表通用工具類
*/
public class ThreadPoolUtils {
/**
* 定義十個線程
*/
private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
/**
* 多線程查全表(通用)
* ThreadPoolExecutor線程池方法
*
* @param totalNum 總條數(shù)
* @param threadTableDataQuery 查詢方法(需要新建接口類)
* @return
*/
public static List<T> threadPool(int totalNum, ThreadTableDataQuery threadTableDataQuery) throws Exception {
//將ArrayList轉(zhuǎn)換為線程安全的SynchronizedList
List<T> result = Collections.synchronizedList(new ArrayList<>(NumberUtils.arrayListRightSize(totalNum)));
// List<T> result = new CopyOnWriteArrayList<>();
//數(shù)據(jù)量超出10 即使用線程異步處理
if (totalNum > 10) {
//將數(shù)據(jù)分組 分成10份 計算每份的條數(shù)
int remainder = totalNum % 10;
int size = remainder > 0 ? totalNum / 10 + 1 : totalNum / 10;
CountDownLatch downLatch = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
int page = i * size;
executor.submit(() -> {
try {
result.addAll(threadTableDataQuery.selectTableData(page, size));
} catch (Exception e) {
e.printStackTrace();
} finally {
downLatch.countDown();
}
});
}
try {
downLatch.await();
} catch (Exception e) {
e.printStackTrace();
}
} else {
result.addAll(threadTableDataQuery.selectTableData(0, 10));
}
return result;
}
}
ThreadTableDataQuery接口
import org.apache.poi.ss.formula.functions.T;
import java.util.List;
public interface ThreadTableDataQuery {
/**
* 線程池接口類 查詢方法
*
* @param page
* @param limit
* @return
* @throws Exception
*/
public List<T> selectTableData(Integer page, Integer limit) throws Exception;
}
interface接口
/**
* 泛型查詢
*
* @param page
* @param limit
* @return
*/
public List<T> selectTableData(Integer page, Integer limit);
server層
/**
* 泛型查詢
*
* @param page
* @param limit
* @return
*/
public List<T> selectTableData(Integer page, Integer limit);
impl層
/**
* 泛型查詢
*
* @param page
* @param limit
* @return
*/
@Override
public List<T> selectTableData(Integer page, Integer limit) {
return testMapper.selectTableData(page,limit);
}
mapper層
import org.apache.ibatis.annotations.Param;
/**
* 泛型查詢
*
* @param
* @return
*/
public List<T> selectTableData(@Param("page") Integer page,
@Param("limit") Integer limit);
xml文件
<select id="selectTableData" parameterType="..." resultMap="...">
select id, test, name from test_table
<if test="page != null">limit #{page},#{limit}</if>
</select>
二 @Async注解方法
controller層
int totalNum = testService.countNum(new testTable());
//重寫多線程中引用的方法
List<T> threadAsync = ThreadPoolUtils.threadAsync(totalNum, new ThreadAsyncTableDataQuery() {
@Override
public Future<List<T>> selectTableDataAsync(Integer page, Integer limit) throws Exception {
return testService.selectTableDataAsync(page, limit);
}
});
//lambda表達(dá)式寫法
//List<T> threadAsync = ThreadPoolUtils.threadAsync(totalNum, (page, limit) -> testService.selectTableDataAsync(page, limit));
//轉(zhuǎn)換為list對象
List<TestTable> test= JSON.parseArray(JSON.toJSONString(threadAsync), testTable.class);
調(diào)用方法和上面線程池方法類似
ThreadPoolUtils
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;
/**
* 多線程查全表通用工具類
*/
public class ThreadPoolUtils {
/**
* 多線程查全表(通用)
* 注解@Async線程方法
*
* @param totalNum
* @param threadAsyncTableDataQuery
* @return
* @throws Exception
*/
public static List<T> threadAsync(int totalNum, ThreadAsyncTableDataQuery threadAsyncTableDataQuery) throws Exception {
List<Future<List<T>>> list = new ArrayList<>();
if (totalNum > 10) {
int remainder = totalNum % 10;
int size = remainder > 0 ? totalNum / 10 + 1 : totalNum / 10;
for (int i = 0; i < 10; i++) {
int page = i * size;
Future<List<T>> pv = threadAsyncTableDataQuery.selectTableDataAsync(page, size);
list.add(pv);
}
} else {
Future<List<T>> ts = threadAsyncTableDataQuery.selectTableDataAsync(0, 10);
list.add(ts);
}
return ThreadPoolUtils.taskValue(list);
}
/**
* 拿取線程里的數(shù)據(jù)
*
* @param taskFutures
* @return
*/
public static List<T> taskValue(List<Future<List<T>>> taskFutures) {
List<T> result = new ArrayList<>();
try {
for (Future<List<T>> future : taskFutures) {
List<T> obj = future.get();
if (null != obj) {
result.addAll(obj);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
ThreadAsyncTableDataQuery接口
import org.apache.poi.ss.formula.functions.T;
import java.util.List;
import java.util.concurrent.Future;
public interface ThreadAsyncTableDataQuery {
/**
* 注解多線程接口類 查詢方法
*
* @param page
* @param limit
* @return
* @throws Exception
*/
public Future<List<T>> selectTableDataAsync(Integer page, Integer limit) throws Exception;
}
server層
/**
* 注解多線程泛型查詢
*
* @param page
* @param limit
* @return
*/
public Future<List<T>> selectTableDataAsync(Integer page, Integer limit);
impl層
核心注解:@Async
不加就相當(dāng)于普通循環(huán)查
import org.springframework.scheduling.annotation.Async;
import java.util.concurrent.Future;
/**
* 注解多線程泛型查詢
*
* @param page
* @param limit
* @return
*/
@Async
@Override
public Future<List<T>> selectTableDataAsync(Integer page, Integer limit) {
List<T> ts = testMapper.selectTableDataAsync(page,limit);
return new AsyncResult<>(ts);
}
mapper層?
import org.apache.ibatis.annotations.Param;
/**
* 注解多線程泛型查詢
*
* @param
* @return
*/
public List<T> selectTableDataAsync(@Param("page") Integer page,
@Param("limit") Integer limit);
xml文件
<select id="selectTableDataAsync" parameterType="..." resultMap="...">
select id, test, name from test_table
<if test="page != null">limit #{page},#{limit}</if>
</select>
啟動程序
加上@EnableAsync注解
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.scheduling.annotation.EnableAsync;
/**
* 啟動程序
*/
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@EnableAsync
public class RuoYiApplication
{
public static void main(String[] args)
{
SpringApplication.run(RuoYiApplication.class, args);
}
速度測試
兩種多線程方法都已介紹完 相比之下@Async更簡便 容易理解些
現(xiàn)在上個測試圖 看下速度
數(shù)據(jù)量約18w條
mybatis-plus耗時:3574ms
線程池方法耗時:541ms
注解多線程耗時:467ms
十次分割limit耗時:3259ms
單個sql耗時:1171ms
測試發(fā)現(xiàn) 兩種多線程方法都比普通的sql查詢快了一倍 當(dāng)數(shù)據(jù)越多時 線程優(yōu)勢越明顯?
最后 兩種封裝的多線程查表方法就講到這里啦文章來源:http://www.zghlxwxcb.cn/news/detail-654096.html
如果寫的有什么問題 或大家有什么有疑問 歡迎評論區(qū)討論哦???文章來源地址http://www.zghlxwxcb.cn/news/detail-654096.html
到了這里,關(guān)于Java多線程查表(封裝方法 多表通用)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!