Java多線(xiàn)程并發(fā)執(zhí)行demo代碼實(shí)例
主類(lèi):MultiThread,執(zhí)行并發(fā)類(lèi)
package java8test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
/**
* @param <H> 為被處理的數(shù)據(jù)類(lèi)型
* @param <T>返回?cái)?shù)據(jù)類(lèi)型
* 知識(shí)點(diǎn)1:X,T為泛型,為什么要用泛型,泛型和Object的區(qū)別請(qǐng)看:https://www.cnblogs.com/xiaoxiong2015/p/12705815.html
*/
public abstract class MultiThread<X, T> {
public static int i = 0;
// 知識(shí)點(diǎn)2:線(xiàn)程池:https://www.cnblogs.com/xiaoxiong2015/p/12706153.html
private final ExecutorService exec; // 線(xiàn)程池
// 知識(shí)點(diǎn)3:@author Doung Lea 隊(duì)列:https://www.cnblogs.com/xiaoxiong2015/p/12825636.html
private final BlockingQueue<Future<T>> queue = new LinkedBlockingQueue<>();
// 知識(shí)點(diǎn)4:計(jì)數(shù)器,還是并發(fā)包大神 @author Doug Lea 編寫(xiě)。是一個(gè)原子安全的計(jì)數(shù)器,可以利用它實(shí)現(xiàn)發(fā)令槍
private final CountDownLatch startLock = new CountDownLatch(1); // 啟動(dòng)門(mén),當(dāng)所有線(xiàn)程就緒時(shí)調(diào)用countDown
private final CountDownLatch endLock; // 結(jié)束門(mén)
private final List<X> listData;// 被處理的數(shù)據(jù)
/**
* @param list list.size()為多少個(gè)線(xiàn)程處理,list里面的H為被處理的數(shù)據(jù)
*/
public MultiThread(List<X> list) {
if (list != null && list.size() > 0) {
this.listData = list;
exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); // 創(chuàng)建線(xiàn)程池,線(xiàn)程池共有nThread個(gè)線(xiàn)程
endLock = new CountDownLatch(list.size()); // 設(shè)置結(jié)束門(mén)計(jì)數(shù)器,當(dāng)一個(gè)線(xiàn)程結(jié)束時(shí)調(diào)用countDown
} else {
listData = null;
exec = null;
endLock = null;
}
}
/**
*
* @return 獲取每個(gè)線(xiàn)程處理結(jié)速的數(shù)組
* @throws InterruptedException
* @throws ExecutionException
*/
public List<T> getResult() throws InterruptedException, ExecutionException {
List<T> resultList = new ArrayList<>();
if (listData != null && listData.size() > 0) {
int nThread = listData.size(); // 線(xiàn)程數(shù)量
for (int i = 0; i < nThread; i++) {
X data = listData.get(i);
Future<T> future = exec.submit(new Task(i, data) {
@Override
public T execute(int currentThread, X data) {
return outExecute(currentThread, data);
}
}); // 將任務(wù)提交到線(xiàn)程池
queue.add(future); // 將Future實(shí)例添加至隊(duì)列
}
startLock.countDown(); // 所有任務(wù)添加完畢,啟動(dòng)門(mén)計(jì)數(shù)器減1,這時(shí)計(jì)數(shù)器為0,所有添加的任務(wù)開(kāi)始執(zhí)行
endLock.await(); // 主線(xiàn)程阻塞,直到所有線(xiàn)程執(zhí)行完成
for (Future<T> future : queue) {
resultList.add(future.get());
}
exec.shutdown(); // 關(guān)閉線(xiàn)程池
}
return resultList;
}
/**
* 每一個(gè)線(xiàn)程執(zhí)行的功能,需要調(diào)用者來(lái)實(shí)現(xiàn)
* @param currentThread 線(xiàn)程號(hào)
* @param data 每個(gè)線(xiàn)程被處理的數(shù)據(jù)
* @return T返回對(duì)象
*/
public abstract T outExecute(int currentThread, X data);
/**
* 線(xiàn)程類(lèi)
*/
private abstract class Task implements Callable<T> {
private int currentThread;// 當(dāng)前線(xiàn)程號(hào)
private X data;
public Task(int currentThread, X data) {
this.currentThread = currentThread;
this.data = data;
}
@Override
public T call() throws Exception {
// startLock.await(); // 線(xiàn)程啟動(dòng)后調(diào)用await,當(dāng)前線(xiàn)程阻塞,只有啟動(dòng)門(mén)計(jì)數(shù)器為0時(shí)當(dāng)前線(xiàn)程才會(huì)往下執(zhí)行
T t = null;
try {
t = execute(currentThread, data);
} finally {
endLock.countDown(); // 線(xiàn)程執(zhí)行完畢,結(jié)束門(mén)計(jì)數(shù)器減1
}
return t;
}
/**
* 每一個(gè)線(xiàn)程執(zhí)行的功能
* @param currentThread 線(xiàn)程號(hào)
* @param data 每個(gè)線(xiàn)程被處理的數(shù)據(jù)
* @return T返回對(duì)象
*/
public abstract T execute(int currentThread, X data);
}
}
結(jié)果類(lèi):ResultVO,保存返回結(jié)果,根據(jù)實(shí)際情況替換成自己的
package java8test;
public class ResultVo {
int i;
public ResultVo(int i) {
this.i = i;
}
public ResultVo() {
// TODO Auto-generated constructor stub
}
}
參數(shù)類(lèi):ParamVO,傳入?yún)?shù)類(lèi),根據(jù)實(shí)際情況替換成自己的
package java8test;
public class ParamVo {
private int i;
ParamVo(int i) {
this.i = i;
}
public int getI() {
return i;
}
@Override
public String toString() {
return String.valueOf(i) + " " + hashCode();
}
}
測(cè)試類(lèi):new兩個(gè)MultiThread,可以看到MultiThread這個(gè)類(lèi)不存在線(xiàn)程安全問(wèn)題。
package java8test;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
try {
List<ParamVo> splitList = new ArrayList<ParamVo>();
for (int i = 0; i < 100; i++) {
splitList.add(new ParamVo(i));
}
List<ParamVo> splitList1 = new ArrayList<ParamVo>();
for (int i = 200; i < 300; i++) {
splitList1.add(new ParamVo(i));
}
MultiThread<ParamVo, ResultVo> multiThread = new MultiThread<ParamVo, ResultVo>(splitList) {
@Override
public ResultVo outExecute(int currentThread, ParamVo data) {
System.out.println("當(dāng)前線(xiàn)程名稱(chēng):" + Thread.currentThread().getName() + "當(dāng)前線(xiàn)程號(hào)=" + currentThread
+ " data=" + data);
i--;
return new ResultVo(data.getI());
}
};
MultiThread<ParamVo, ResultVo> multiThread1 = new MultiThread<ParamVo, ResultVo>(splitList1) {
@Override
public ResultVo outExecute(int currentThread, ParamVo data) {
System.out.println("當(dāng)前線(xiàn)程名稱(chēng):" + Thread.currentThread().getName() + "當(dāng)前線(xiàn)程號(hào)=" + currentThread
+ " data=" + data);
i--;
return new ResultVo(data.getI());
}
};
List<ResultVo> list = multiThread.getResult();
List<ResultVo> list1 = multiThread1.getResult();
// 獲取每一批次處理結(jié)果
System.out.println("獲取處理結(jié)果........................");
for (ResultVo vo : list) {
System.out.println(vo.i);
}
System.out.println("獲取1處理結(jié)果........................");
for (ResultVo vo : list1) {
System.out.println(vo.i);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
這個(gè)類(lèi)也用在了生產(chǎn)當(dāng)中,用來(lái)并發(fā)插入數(shù)據(jù)。但是事務(wù)不能被管控,需要自己保證最終事務(wù)一致。需要注意。


以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 簡(jiǎn)述Java中進(jìn)程與線(xiàn)程的關(guān)系_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
- java中進(jìn)程與線(xiàn)程_三種實(shí)現(xiàn)方式總結(jié)(必看篇)
- java多線(xiàn)程之線(xiàn)程,進(jìn)程和Synchronized概念初解
- java高并發(fā)之理解進(jìn)程和線(xiàn)程
- Java多線(xiàn)程高并發(fā)中解決ArrayList與HashSet和HashMap不安全的方案
- java多線(xiàn)程之并發(fā)工具類(lèi)CountDownLatch,CyclicBarrier和Semaphore
- Java的線(xiàn)程與進(jìn)程以及線(xiàn)程的四種創(chuàng)建方式
- Java并發(fā)編程之volatile與JMM多線(xiàn)程內(nèi)存模型
- Java多線(xiàn)程并發(fā)與并行和線(xiàn)程與進(jìn)程案例
相關(guān)文章
MyBatis學(xué)習(xí)教程(六)-調(diào)用存儲(chǔ)過(guò)程
這篇文章主要介紹了MyBatis學(xué)習(xí)教程(六)-調(diào)用存儲(chǔ)過(guò)程的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起看下吧2016-05-05
Java使用DateTimeFormatter實(shí)現(xiàn)格式化時(shí)間
這篇文章主要介紹了Java使用DateTimeFormatter實(shí)現(xiàn)格式化時(shí)間,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
Spring實(shí)現(xiàn)Quartz自動(dòng)配置的方法詳解
這篇文章主要介紹了Spring實(shí)現(xiàn)Quartz自動(dòng)配置的方法詳解,如果想在應(yīng)用中使用Quartz任務(wù)調(diào)度功能,可以通過(guò)Spring Boot實(shí)現(xiàn)Quartz的自動(dòng)配置,以下介紹如何開(kāi)啟Quartz自動(dòng)配置,以及Quartz自動(dòng)配置的實(shí)現(xiàn)過(guò)程,需要的朋友可以參考下2023-11-11
mybatis學(xué)習(xí)筆記之mybatis注解配置詳解
本篇文章主要介紹了mybatis學(xué)習(xí)筆記之mybatis注解配置詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
Junit測(cè)試多線(xiàn)程無(wú)法得到結(jié)果的問(wèn)題解決
在測(cè)試一個(gè)文件轉(zhuǎn)換工具類(lèi)的時(shí)候,發(fā)生一個(gè)有趣的現(xiàn)象,同樣的輸入,使用Main函數(shù)可以正確解析,得到結(jié)果,使用Junit卻無(wú)法得到結(jié)果,神奇的是,即使捕獲Throwable,也無(wú)法捕獲到仍和異常。2021-05-05
Java中的遞增i++與++i的實(shí)現(xiàn)原理詳解
這篇文章主要介紹了Java中的i++與++i的實(shí)現(xiàn)原理詳解,在Java中,i++是一種常見(jiàn)的遞增操作符,用于將變量i的值增加1,它是一種簡(jiǎn)潔且方便的方式來(lái)實(shí)現(xiàn)循環(huán)和計(jì)數(shù)功能,i++可以用于各種情況,本文來(lái)看一下其實(shí)現(xiàn)原理,需要的朋友可以參考下2023-10-10
java解析dbf之通過(guò)javadbf包生成和讀取dbf文件
這篇文章主要介紹了java通過(guò)javadbf讀取和生成DBF文件的方法,大家參考使用吧2014-01-01

