Java随笔(1) 线程池使用异常

2020-03-21  本文已影响0人  sunyelw

昨天晚上定位个问题花了好久,诶,还是菜啊~


先上代码(稍作修改)

private <T> List<T> parseFile(String fileName, String filePath, int number, List<String> errList) {

    List<T> userList = new ArrayList <>(number);
    String nowPath = filePath + "/" + fileName;

    // es
    int ths = TaskUtil.getThs(number, EVERY_SIZE);
    ExecutorService tape = TaskUtil.getEs(ths, "parse-" + fileName);
    try (BufferedReader bs =
                 new BufferedReader(
                         new InputStreamReader(
                                 new FileInputStream(nowPath), "GBK"))) {
        String line;
        while ((line = bs.readLine()) != null) {
            String finalLine = line;
            tape.execute(() -> {
                T bu;
                if ((bu = parseLine(finalLine, errList)) != null) userList.add(bu);
            });
        }
        return userList;
    } catch (Exception e) {
        log.error("ag_error_parse_file filePath: {}", nowPath, e);
        return new ArrayList <>();
    } finally {
        tape.shutdown();
    }
}

需求描述:多线程解析一个文件,存到一个List中返回。
前提:不想显示定义线程类,比如Callable或Runnable的实现,减少代码量
问题描述:解析没问题,但返回的List时空时不空。

执行流程简化

这里总共有两个致命问题

改动一下

private <T> List<T> parseFile(String fileName, String filePath, int number, List<String> errList) {

    List<T> userList = Collections.synchronizedList(new ArrayList <>());
    String nowPath = filePath + "/" + fileName;

    // es
    int ths = TaskUtil.getThs(number, EVERY_SIZE);
    ExecutorService tape = TaskUtil.getEs(ths, "parse-" + fileName);
    try (BufferedReader bs =
                 new BufferedReader(
                         new InputStreamReader(
                                 new FileInputStream(nowPath), "GBK"))) {
        String line;
        while ((line = bs.readLine()) != null) {
            String finalLine = line;
            tape.execute(() -> parseLine(finalLine, errList, userList));
        }
        tape.shutdown();
        while (true) {
            if (tape.isTerminated()) {
                return userList;
            }
            Thread.sleep(100);
        }
    } catch (Exception e) {
        log.error("ag_error_parse_file filePath: {}", nowPath, e);
        return new ArrayList <>();
    } finally {
        if (!tape.isTerminated()) tape.shutdownNow();
    }
}

针对以上两点做的改动


我看过ArrayList的源码,也看过 ThreadPoolExecutor 的实现,但还是会犯这种"低级错误",这提醒我敲代码时应该要更加细心点,多想想,谋定而后动。

吾日三省。

上一篇 下一篇

猜你喜欢

热点阅读