为了账号安全,请及时绑定邮箱和手机立即绑定

带有打开文件的 Java 多线程

带有打开文件的 Java 多线程

饮歌长啸 2021-12-22 20:14:49
我有一个 txt 文件:order_me.txt,其中有一些整数需要使用 4 个线程进行排序。他们需要同时工作,但不能做同样的事情。我已经设法对整数进行排序,但有些东西不正常......这是线程类:public class Threading {    static List<Integer> integersCopy = new ArrayList<>();    public static void main(String[] args) {        openFile();        Thread t1 = new Thread(new Command("thread 1", integersCopy));        t1.start();        Thread t2 = new Thread(new Command("thread 2", integersCopy));        t2.start();        Thread t3 = new Thread(new Command("thread 3", integersCopy));        t3.start();        Thread t4 = new Thread(new Command("thread 4", integersCopy));        t4.start();        try {            if (t1.isAlive())                t1.join();            if (t2.isAlive())                t2.join();            if (t3.isAlive())                t3.join();            if (t4.isAlive())                t4.join();        } catch (Exception e) {            System.out.println("Exception with threads");        }    }    public static void openFile() {        File file = new File("order_me.txt");        try {            Scanner scanner = new Scanner(file);            List<Integer> integers = new ArrayList<>();            while (scanner.hasNext()) {                if (scanner.hasNextInt()) {                    integers.add(scanner.nextInt());                } else {                    scanner.next();                }            }            integersCopy = integers;            System.out.println("File opened successfully");        } catch (Exception e) {            System.out.println("Triggered exception");        }    }这是排序类:    import java.util.Collections;    import java.util.List;    public class Command implements Runnable {    String threadName;    List<Integer> listOfInts;    Command(String name, List<Integer> list) {        threadName = name;        listOfInts = list;    }        }    }}
查看完整描述

2 回答

?
素胚勾勒不出你

TA贡献1827条经验 获得超9个赞

一旦一个线程对整数进行了排序,尝试在多个线程中做同样的事情就没有意义了,事实上,因为这不是以线程安全的方式完成的,你很可能会破坏列表。

简而言之,使用一个线程。


查看完整回答
反对 回复 2021-12-22
?
喵喔喔

TA贡献1735条经验 获得超5个赞

您正在改变List多个线程上的共享。ArrayList不是线程安全的:您需要使用线程安全Collection或使用Collections.synchronizedList.

如果您在每个线程中对相同的列表进行排序,那么您的实现可能是错误的:

  • 您应该在父线程中阅读一次列表

  • 您应该按线程数拆分列表,并对每个自己的线程中的每个子列表进行排序。这就是Thread在这种情况下的目的:分工去做。

  • 然后您应该在父线程中加入子列表:在加入过程中,您将不得不进行排序。由于每个子列表都已排序,因此您可以使用更快的排序(例如:如果子列表 A 的第一个项目在子列表 B 的最后一个之后,那么您可以将 A 的所有项目添加到 B 中)或标准排序。

此外,您可能Stream会这样做:

  • parallel()方法是Stream使用多个线程的原因。

  • ForkJoinPool用于使用另一个线程池(请参阅此 SO 答案)。举个例子可能没用。

  • 遗憾的是,Scanner不能转换为IntStreamStream。您需要使用Files.lines和 aPattern用空格 ( \s+)分割行。

  • 我们使用flatMapToInt要转换为IntStreamOptionalInt(这将是空的无效数字,例如:*a4)。

  • sorted()确保我们使用默认排序进行排序。使用比较器进行排序需要一个普通的 Stream,因此,将flatMapToInt其更改为flatMap.

  • toArray()在这种情况下可能比在第二个示例中使用ArrayListof更好Integer

使用 Java 11 测试的代码:

  public static void main(final String[] args) throws Exception {

    final Pattern splitter = Pattern.compile("\\s+");

    // see

    // 

    final ForkJoinPool forkJoinPool = new ForkJoinPool();

    final Future<int[]> future = forkJoinPool.submit(() -> {

      try (final Stream<String> lines = Files.lines(Paths.get("myfile.txt"), StandardCharsets.UTF_8)) {

        return lines.parallel() // use default parallel ExecutorService

            .flatMap(splitter::splitAsStream) // tokenize input

            .flatMapToInt(s -> parseInt(s).stream()) // convert to number (eg: nextInt())

            .sorted().toArray();

      }

    });


    final int[] result = future.get();

    System.out.println("result.length: " + result.length);

    // Arrays.stream(result).forEach(System.out::println);

    final Future<List<Integer>> future2 = forkJoinPool.submit(() -> {

      try (Stream<String> lines = Files.lines(Paths.get("myfile.txt"), StandardCharsets.UTF_8)) {

        return lines.parallel() // use default parallel ExecutorService

            .flatMap(splitter::splitAsStream) // tokenize input

            .flatMapToInt(s -> parseInt(s).stream()) // convert to number (eg: nextInt())

            .sorted().collect(ArrayList::new, List::add, List::addAll) // probably best to use

                                                                       // array.

        ;

      }

    });

    final List<Integer> result2 = future2.get();

    System.out.println("result2.length: " + result2.size());

  }


  static OptionalInt parseInt(final String s) {

    try {

      return OptionalInt.of(Integer.parseInt(s));

    } catch (final NumberFormatException e) {

      return OptionalInt.empty();

    }

  }


查看完整回答
反对 回复 2021-12-22
  • 2 回答
  • 0 关注
  • 254 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号