Demo04.java 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package J20250805.demo01;
  2. import java.io.*;
  3. import java.util.*;
  4. import java.util.concurrent.*;
  5. /**
  6. * @author WanJl
  7. * @version 1.0
  8. * @title Demo04
  9. * @description
  10. * 并发文件去重
  11. * 需求:
  12. * - 多线程读取多个日志文件(`log1.txt`、`log2.txt`...),提取所有 URL(假设每行一个 URL)
  13. * - 使用线程安全的集合存储不重复的 URL
  14. * - 所有线程执行完毕后,将去重后的 URL 按字母顺序写入`unique_urls.txt`
  15. * @create 2025/8/5
  16. */
  17. public class Demo04 {
  18. //创建一个集合:要求线程安全,存储不重复的元素
  19. // Set newSetFromMap(Map<> map) 该方法的参数是Map类型对象,返回值是Set类型对象
  20. //作用就是将一个Map集合对象转换为Set集合。Map的key就是不能重复的,其实就是Set
  21. private static Set<String> set=Collections.newSetFromMap(new ConcurrentHashMap<>());
  22. /**
  23. * 先处理单个日志文件,并且把URL添加到线程安全的集合中
  24. * @param fileName
  25. */
  26. private static void processLogFile(String fileName){
  27. try(BufferedReader br=new BufferedReader(new FileReader(fileName))) {
  28. String url;
  29. while ((url= br.readLine())!=null){
  30. url=url.trim();//去掉空格
  31. if (!url.isEmpty()){
  32. set.add(url);
  33. }
  34. }
  35. } catch (FileNotFoundException e) {
  36. e.printStackTrace();
  37. } catch (IOException e) {
  38. e.printStackTrace();
  39. }
  40. System.out.println("完成处理文件"+fileName);
  41. }
  42. /**
  43. * 将去重后的 URL 按字母顺序写入`unique_urls.txt`
  44. * @param outputFileName
  45. */
  46. private static void writeUniqueUrlsToFile(String outputFileName){
  47. //先把集合转换为列表并且进行排序
  48. List<String> list=new ArrayList<>(set);
  49. Collections.sort(list);
  50. //写入文件
  51. try(BufferedWriter bw=new BufferedWriter(new FileWriter(outputFileName))){
  52. for (String url:list){
  53. bw.write(url);
  54. bw.newLine();
  55. }
  56. } catch (IOException e) {
  57. e.printStackTrace();
  58. }
  59. }
  60. public static void main(String[] args) {
  61. List<String> logFiles=Arrays.asList ("log1.txt","log2.txt","log3.txt");
  62. //创建线程池
  63. ExecutorService executorService = Executors.newFixedThreadPool(5);
  64. for (int i = 0; i < logFiles.size(); i++) {
  65. int t=i;
  66. executorService.submit(()->{
  67. processLogFile(logFiles.get(t));
  68. });
  69. }
  70. writeUniqueUrlsToFile("unique_urls.txt");
  71. }
  72. }