Java多個(gè)線程同時(shí)執(zhí)行的方法
java多個(gè)線程同時(shí)執(zhí)行
方法一:使用CountDownLatch工具,使用await方法阻塞需要同時(shí)執(zhí)行的線程,最后調(diào)用countDown方法,將計(jì)數(shù)器減為0時(shí),所有阻塞的線程就會(huì)同時(shí)執(zhí)行。

public void threadConcurretDemo1() throws InterruptedException{
int size = 3;
// 初始計(jì)數(shù)器值為1
CountDownLatch countDownLatch = new CountDownLatch(1);
for (int i = 0; i < size; i++) {
new Thread(()->{
try {
// 阻塞當(dāng)前線程,直到計(jì)數(shù)器值減少為0,才開(kāi)始執(zhí)行
countDownLatch.await();
System.out.println(System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
// 讓主線程休眠下,讓上面的線程準(zhǔn)備好
Thread.sleep(500);
// 計(jì)數(shù)器的值減1,如果為0,阻塞的線程就會(huì)繼續(xù)往下執(zhí)行
countDownLatch.countDown();
}
方法二:使用CyclicBarrier,當(dāng)使用await阻塞的線程數(shù)到達(dá)柵欄總數(shù)后,就會(huì)同時(shí)執(zhí)行,阻塞線程數(shù)變?yōu)?,等阻塞的線程數(shù)再次達(dá)到柵欄總數(shù)后,就又會(huì)同時(shí)執(zhí)行一批;

public void threadConcurretDemo2() throws InterruptedException{
int size = 3;
// 設(shè)置柵欄總數(shù)
CyclicBarrier cyclicBarrier = new CyclicBarrier(size);
for (int i = 0; i < 6; i++) {
Thread.sleep(100);
new Thread(()->{
try {
// 阻塞當(dāng)前線程,直到參與線程到達(dá)柵欄總數(shù)
cyclicBarrier.await();
System.out.println("開(kāi)始執(zhí)行" + System.currentTimeMillis());
Thread.sleep((long) (Math.random() * 1000));
System.out.println("結(jié)束執(zhí)行" +System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
Java多線程處理文件詳解與代碼示例
在Java編程中,文件處理是一項(xiàng)常見(jiàn)的任務(wù)。當(dāng)需要處理大量文件或處理文件的時(shí)間較長(zhǎng)時(shí),單線程的處理方式可能會(huì)顯得效率低下。為了提高文件處理的效率,我們可以使用多線程技術(shù)。本文將詳細(xì)介紹如何使用Java多線程來(lái)處理文件,并提供一個(gè)詳細(xì)的代碼示例,該示例可以直接運(yùn)行。
一、多線程處理文件的基本概念
多線程是指在一個(gè)程序中同時(shí)運(yùn)行多個(gè)線程,每個(gè)線程完成特定的任務(wù)。在處理文件時(shí),可以將文件的讀取、解析、寫入等步驟拆分成多個(gè)任務(wù),使用多個(gè)線程并行處理,從而提高處理效率。
多線程處理文件的主要優(yōu)勢(shì)包括:
- 提高處理速度:多個(gè)線程并行處理文件,可以充分利用多核CPU的計(jì)算能力。
- 減少處理時(shí)間:通過(guò)并行處理,可以顯著減少處理大量文件所需的時(shí)間。
- 提高資源利用率:多線程可以有效利用系統(tǒng)資源,如內(nèi)存和I/O設(shè)備。
二、Java多線程處理文件的實(shí)現(xiàn)方式
Java提供了多種實(shí)現(xiàn)多線程的方式,包括繼承Thread類、實(shí)現(xiàn)Runnable接口和使用ExecutorService等。其中,使用ExecutorService來(lái)管理線程池是較為推薦的方式,因?yàn)樗屿`活和強(qiáng)大。
1. 繼承Thread類
這是最基本的實(shí)現(xiàn)多線程的方式,通過(guò)繼承Thread類并重寫其run方法來(lái)實(shí)現(xiàn)多線程。但這種方式不夠靈活,因?yàn)镴ava不支持多繼承。
2. 實(shí)現(xiàn)Runnable接口
通過(guò)實(shí)現(xiàn)Runnable接口,可以將線程任務(wù)與線程對(duì)象分離,更加靈活和推薦。
3. 使用ExecutorService
ExecutorService是一個(gè)用于管理線程池的服務(wù)框架,它提供了更加靈活和強(qiáng)大的線程管理能力。通過(guò)ExecutorService,可以方便地提交任務(wù)、管理線程池和關(guān)閉線程池。
三、代碼示例
下面是一個(gè)使用ExecutorService來(lái)處理文件的詳細(xì)代碼示例。該示例假設(shè)我們需要從一個(gè)目錄中讀取多個(gè)文件,并對(duì)每個(gè)文件進(jìn)行簡(jiǎn)單的處理(如讀取文件內(nèi)容并輸出到控制臺(tái))。
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class MultiThreadFileProcessor {
// 定義線程池大小
private static final int THREAD_POOL_SIZE = 10;
public static void main(String[] args) {
// 指定要處理的文件目錄
String directoryPath = "path/to/your/directory";
// 獲取目錄下的所有文件
List<File> files = getFilesFromDirectory(directoryPath);
// 創(chuàng)建線程池
ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
// 提交任務(wù)給線程池
List<Future<String>> futures = new ArrayList<>();
for (File file : files) {
Callable<String> task = new FileProcessingTask(file);
futures.add(executorService.submit(task));
}
// 關(guān)閉線程池(不再接受新任務(wù))
executorService.shutdown();
// 等待所有任務(wù)完成并獲取結(jié)果
for (Future<String> future : futures) {
try {
// 獲取任務(wù)的處理結(jié)果
String result = future.get();
System.out.println(result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
// 獲取目錄下的所有文件
private static List<File> getFilesFromDirectory(String directoryPath) {
List<File> files = new ArrayList<>();
File directory = new File(directoryPath);
if (directory.exists() && directory.isDirectory()) {
File[] fileArray = directory.listFiles();
if (fileArray != null) {
for (File file : fileArray) {
if (file.isFile()) {
files.add(file);
}
}
}
}
return files;
}
// 文件處理任務(wù)類
static class FileProcessingTask implements Callable<String> {
private File file;
public FileProcessingTask(File file) {
this.file = file;
}
@Override
public String call() throws Exception {
StringBuilder sb = new StringBuilder();
sb.append("Processing file: ").append(file.getName()).append("\n");
// 使用BufferedReader讀取文件內(nèi)容
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
} catch (IOException e) {
sb.append("Error processing file: ").append(file.getName()).append(" - ").append(e.getMessage()).append("\n");
}
return sb.toString();
}
}
}四、代碼詳解
定義線程池大小:
private static final int THREAD_POOL_SIZE = 10;
定義了一個(gè)常量THREAD_POOL_SIZE來(lái)表示線程池的大小,這里設(shè)置為10。
獲取要處理的文件:
List<File> files = getFilesFromDirectory(directoryPath);
使用getFilesFromDirectory方法獲取指定目錄下的所有文件。
創(chuàng)建線程池:
ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
使用Executors.newFixedThreadPool方法創(chuàng)建一個(gè)固定大小的線程池。
提交任務(wù)給線程池:
for (File file : files) {
Callable<String> task = new FileProcessingTask(file);
futures.add(executorService.submit(task));
}對(duì)于每個(gè)文件,創(chuàng)建一個(gè)FileProcessingTask任務(wù),并將其提交給線程池。任務(wù)的結(jié)果存儲(chǔ)在futures列表中。
關(guān)閉線程池:
executorService.shutdown();
調(diào)用shutdown方法關(guān)閉線程池,表示不再接受新任務(wù)。
等待所有任務(wù)完成并獲取結(jié)果:
for (Future<String> future : futures) {
try {
String result = future.get();
System.out.println(result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}使用future.get()方法等待每個(gè)任務(wù)的完成并獲取結(jié)果。如果任務(wù)執(zhí)行過(guò)程中出現(xiàn)異常,將異常信息打印到控制臺(tái)。
文件處理任務(wù)類:
static class FileProcessingTask implements Callable<String> {
// ...
}FileProcessingTask類實(shí)現(xiàn)了Callable<String>接口,并重寫了call方法。在call方法中,使用BufferedReader讀取文件內(nèi)容,并將讀取到的內(nèi)容存儲(chǔ)在StringBuilder對(duì)象中。最后返回處理結(jié)果。
五、總結(jié)
通過(guò)本文的介紹和代碼示例,我們了解了如何使用Java多線程來(lái)處理文件。使用多線程技術(shù)可以顯著提高文件處理的效率,特別是對(duì)于大量文件的處理任務(wù)。在實(shí)際應(yīng)用中,可以根據(jù)具體需求調(diào)整線程池的大小和文件處理任務(wù)的實(shí)現(xiàn)方式。希望本文對(duì)你有所幫助,如果你有任何問(wèn)題或建議,請(qǐng)隨時(shí)留言交流。
到此這篇關(guān)于Java多個(gè)線程同時(shí)執(zhí)行的方法的文章就介紹到這了,更多相關(guān)java多個(gè)線程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot+MybatisPlus+代碼生成器整合示例
這篇文章主要介紹了SpringBoot+MybatisPlus+代碼生成器整合示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
一文帶你徹底了解Java8中的Lambda,函數(shù)式接口和Stream
這篇文章主要為大家詳細(xì)介紹了解Java8中的Lambda,函數(shù)式接口和Stream的用法和原理,文中的示例代碼簡(jiǎn)潔易懂,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-08-08
Java訪問(wèn)者模式實(shí)現(xiàn)優(yōu)雅的對(duì)象結(jié)構(gòu)處理
Java訪問(wèn)者模式是一種行為型設(shè)計(jì)模式,它通過(guò)將數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)操作分離,實(shí)現(xiàn)對(duì)復(fù)雜對(duì)象結(jié)構(gòu)的處理。它將數(shù)據(jù)結(jié)構(gòu)中的每個(gè)元素都轉(zhuǎn)換為訪問(wèn)者能夠識(shí)別的形式,從而使得數(shù)據(jù)操作可以在不影響數(shù)據(jù)結(jié)構(gòu)的前提下進(jìn)行擴(kuò)展和變化2023-04-04
火遍全網(wǎng)的Hutool使用Builder模式創(chuàng)建線程池的方法
這篇文章主要介紹了火遍全網(wǎng)的Hutool使用Builder模式創(chuàng)建線程池的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
SpringSecurity之SecurityContextHolder使用解讀
這篇文章主要介紹了SpringSecurity之SecurityContextHolder使用解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
spring?boot獲取session的值為null問(wèn)題及解決方法
我在登陸的時(shí)候,登陸成功后將name存進(jìn)了session,然后在獲取個(gè)人信息時(shí)取出session里的name的值為null,接下來(lái)通過(guò)本文給大家分享springboot獲取session的值為null問(wèn)題,需要的朋友可以參考下2023-05-05

