Почему задачи с и без ExecutorService занимают одинаковое количество времени? - PullRequest
0 голосов
/ 28 октября 2019

У меня есть следующая структура проекта при весенней загрузке с использованием шаблона JDBC и службы executor. Приложение занимает почти одинаковое количество времени с потоком и без потока. Я ожидал, что сокращение времени составит не менее одной трети.

Я прочитал следующее по этой ссылке , но я не знаю, как применить в своем коде:

Чтобы иметь возможность использовать транзакции с нашим потоком, нам нужно понять, как транзакции работают с пружиной. Весной информация о транзакции хранится в переменных ThreadLocal. Поэтому эти переменные характерны для текущей транзакции в одном потоке.

Является ли моя долгосрочная задача в SqlUtilities.executeSql(sqlName, values, dataSource) причиной проблемы?

Кто-нибудь знает почему? Любое решение приветствуется.

@SpringBootApplication
public class ApplicationMain implements CommandLineRunner {
    @Autowired
    @Qualifier(value = "mainExecutorService")
    public ExecutorService mainExecutorService;

    @Autowired
    @Qualifier(value = "mut")
    public Mut mut;

    @Autowired
    @Qualifier(value = "apt")
    public Apt apt;

    public static void main(String[] args){
        SpringApplication.run(ApplicationMain.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        try {
            // First thread
            mainExecutorService.submit(() -> {
                mut.initialise("2019", "10", "31");
                apt.sum();
            }, true);

            // Second thread
            mainExecutorService.submit(() -> {
                apt.initialise("2019", "10", "31");
                mut.sum();
            }, true);
            mainExecutorService.shutdown();

            if (mainExecutorService.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES))
                System.out.println("done");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            mainExecutorService.shutdownNow();
        }
    }
}

конфигурация

@Configuration
class ExecutorservicConfig {
    @Bean("mainExecutorService")
    public ExecutorService mainExecutorService() {
        return Executors.newFixedThreadPool(2);
    }

    @Bean(name = "apt")
    public Apt createApt(){
        return new Apt();
    }

    @Bean(name = "mut")
    public Mut createMut(){
        return new Mut();
    }
}

Интерфейс

    interface Som {
    ExecutorService service = Executors.newCachedThreadPool();
    void initialize (String year, String month, String day);
    void sum();
    void deleteInsertUpdate();
    void execute();
    void print();
}

Первый класс рассматривает выполнение в первом потоке

    class Mut implements Som {
    private String year, month, day ;

    @Autowired
    @Qualifier(value = "jdbcTemplate")
    private JdbcTemplate jdbcTemplate;
    private long staringProcessingTime;

    @Override
    public void initialize (String year, String month, String day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

    @Override
    public void sum() {
        staringProcessingTime = System.currentTimeMillis();
        System.out.println("Started first thread. starting time is:".concat(String.valueOf(staringProcessingTime)));
        deleteInsertUpdate();
    }

    @Override
    public void deleteInsertUpdate() {
        String queryDelete = "";
        String queryInsert = "";
        String queryUpdate = "";

        try {
            service.submit(() -> jdbcTemplate.update(queryDelete));
            service.submit(() -> jdbcTemplate.update(queryInsert));
            service.submit(() -> jdbcTemplate.update(queryUpdate));
            service.shutdown();
            if (service.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES))
                execute();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            service.shutdownNow();
        }
    }

    @Override
    public void execute() {
        // long running task here ....
        if( SqlUtilities.executeSql(sqlName, values, dataSource) )
            print();
    }

    @Override
    public void print() {
        long endProcessingTime = System.currentTimeMillis();
        System.out.println("Ended first thread. total time in millisecond:".concat(String.valueOf(endProcessingTime - staringProcessingTime)));
    }

}

Второй класс считает выполнение во втором потоке.

class Apt implements Som {
    private String year, month, day ;
    private long staringProcessingTime;

    @Autowired
    @Qualifier(value = "jdbcTemplate")
    private JdbcTemplate jdbcTemplate;

    @Override
    public void initialize (String year, String month, String day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

    @Override
    public void sum() {
        staringProcessingTime = System.currentTimeMillis();
        System.out.println("Started Second thread. starting time is:".concat(String.valueOf(staringProcessingTime)));
        deleteInsertUpdate();
    }

    @Override
    public void deleteInsertUpdate() {
        String queryDelete = "";
        String queryInsert = "";
        String queryUpdate = "";

        try {
            service.submit(() -> jdbcTemplate.update(queryDelete));
            service.submit(() -> jdbcTemplate.update(queryInsert));
            service.submit(() -> jdbcTemplate.update(queryUpdate));
            service.shutdown();
            if (service.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES))
                execute();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            service.shutdownNow();
        }
    }

    @Override
    public void execute() {
        // long running task here ....
        if( SqlUtilities.executeSql(sqlName, values, dataSource) )
            print();
    }

    @Override
    public void print() {
        long endProcessingTime = System.currentTimeMillis();
        System.out.println("Ended second thread. total time in millisecond:".concat(String.valueOf(endProcessingTime - staringProcessingTime)));
    }

}

Утилиты класс

class SqlUtilities {

public static boolean executeSql(String sqlName, Map<String,String> values, DataSource dataSource){
    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    boolean executed = false;
    try{
        Resource[] resources = resolver.getResources("classpath*:sql/*.sql");

        for(Resource resource: resources)
        {
            if(sqlName.equals(resource.getFilename()))
            {
                File tempFile = File.createTempFile(resource.getFilename(), ".sql");
                Path tempPath = Paths.get(tempFile.getAbsolutePath());
                try (InputStream inputStream = resource.getInputStream()) {
                    FileUtils.copyInputStreamToFile(inputStream, tempFile);

                    String contents = new String(Files.readAllBytes(tempPath));
                    String newContents = StringSubstitutor.replace(contents, values);

                    Files.write(tempPath, Collections.singleton(newContents), StandardOpenOption.TRUNCATE_EXISTING);

                    Resource tempResource = new FileUrlResource(tempPath.toString());
                    ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(tempResource);
                    databasePopulator.execute(dataSource);
                } finally {
                    executed = Files.deleteIfExists(tempPath);
                }
            }
        }
    }catch (Exception e){
        System.out.println(e.getMessage());;
    }

    return executed;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...