帮忙出一个 多线程在实际项目中的示例
下文笔者讲述使用多线程处理日志文件压缩和移动的示例分享
日志文件压缩和移动
项目结构 log-processing/ ├── src/ │ └── main/ │ └── java/ │ └── com/ │ └── example/ │ └── logprocessing/ │ ├── LogProcessor.java │ ├── LogTask.java │ └── MainApp.java ├── logs/ │ └── access_20231010.log ├── target/ │ └── logs/ │ └── access_20231010.log.tar.gz └── pom.xml
1.`LogTask.java`
`LogTask`类实现`Callable`接口
用于处理单个日志文件的压缩和移动操作
package com.example.logprocessing;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.Callable;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class LogTask implements Callable<Boolean> {
private final File logFile;
private final Path targetDir;
public LogTask(File logFile, Path targetDir) {
this.logFile = logFile;
this.targetDir = targetDir;
}
@Override
public Boolean call() throws Exception {
try {
// 构建压缩文件名
Path compressedFilePath = targetDir.resolve(logFile.getName() + ".tar.gz");
// 压缩文件
compressFile(logFile.toPath(), compressedFilePath);
// 删除原日志文件
if (logFile.delete()) {
System.out.println("Deleted original log file: " + logFile.getAbsolutePath());
return true;
} else {
System.err.println("Failed to delete original log file: " + logFile.getAbsolutePath());
return false;
}
} catch (IOException e) {
System.err.println("Error processing log file: " + logFile.getAbsolutePath());
e.printStackTrace();
return false;
}
}
private void compressFile(Path source, Path target) throws IOException {
try (ZipOutputStream zos = new ZipOutputStream(new GZIPOutputStream(Files.newOutputStream(target)))) {
ZipEntry zipEntry = new ZipEntry(source.getFileName().toString());
zos.putNextEntry(zipEntry);
byte[] bytes = Files.readAllBytes(source);
zos.write(bytes, 0, bytes.length);
zos.closeEntry();
}
}
}
2.`LogProcessor.java`
`LogProcessor`类负责管理线程池 分配任务并监控任务的执行情况
package com.example.logprocessing; import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arraylist; import java.util.List; import java.util.concurrent.*; public class LogProcessor { private final Path logDir; private final Path targetDir; private final ExecutorService executorService; public LogProcessor(String logDirPath, String targetDirPath, int threadPoolSize) { this.logDir = Paths.get(logDirPath); this.targetDir = Paths.get(targetDirPath); this.executorService = Executors.newFixedThreadPool(threadPoolSize); } public void processLogs() { try { // 获取前一天的日期 String yesterday = java.time.LocalDate.now(). minusDays(1).format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd")); // 创建目标目录(如果不存在) Files.createDirectories(targetDir); // 获取前一天的日志文件 File[] logFiles = logDir.toFile(). listFiles((dir, name) -> name.contains(yesterday)); if (logFiles == null || logFiles.length == 0) { System.out.println("No log files found for " + yesterday); return; } // 提交任务到线程池 List<Future<Boolean>> futures = new ArrayList<>(); for (File logFile : logFiles) { LogTask task = new LogTask(logFile, targetDir); futures.add(executorService.submit(task)); } // 等待所有任务完成 for (Future<Boolean> future : futures) { try { if (future.get()) { System.out.println("Log file processed successfully."); } else { System.err.println("Log file processing failed."); } } catch (InterruptedException | ExecutionException e) { System.err.println("Error processing log file."); e.printStackTrace(); } } } catch (IOException e) { System.err.println("Error creating target directory."); e.printStackTrace(); } finally { executorService.shutdown(); } } }
3.`MainApp.java`
`MainApp` 类是应用程序的入口
负责初始化`LogProcessor`
并调用`processLogs`方法
package com.example.logprocessing;
public class MainApp {
public static void main(String[] args) {
// 定义日志目录和目标目录
String logDirPath = "/usr/local/tomcat/TEST_CUBE/logs";
String targetDirPath = "/data/nasdisk/applogs/TEST_CUBE";
// 定义线程池大小
int threadPoolSize = 5;
// 初始化 LogProcessor
LogProcessor logProcessor = new LogProcessor(logDirPath, targetDirPath, threadPoolSize);
// 处理日志文件
logProcessor.processLogs();
}
}
4.`pom.xml`(Maven 项目)
使用Maven来管理项目 可添加以下`pom.xml`文件
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>log-processing</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!-- 添加必要的依赖项 -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
</plugins>
</build>
</project>
5.配置cron任务
使用 cron 任务每天凌晨运行该脚本。
1.编辑cron任务:
sudo crontab -e
2.添加cron任务:
0 1 * * * /usr/bin/java -cp /path/to/log-processing.jar
com.example.logprocessing.MainApp >> /var/log/log_processing.log 2>&1
- `0 1 * * *`:每天凌晨1点运行脚本。
- `/usr/bin/java -cp /path/to/log-processing.jar com.example.logprocessing.MainApp`:
运行 Java 应用程序。
- `>> /var/log/log_processing.log 2>&1`:将标准输出和标准错误输出重定向到日志文件。
3.保存并退出:
- 在 `vi` 或 `nano` 中保存并退出编辑器
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。


