Java 多线程优化与测试

如果你不相信努力和时光,那么成果就会是第一个选择辜负你的。不要去否定你自己的过去,也不要用你的过去牵扯你现在的努力和对未来的展望。不是因为拥有希望你才去努力,而是去努力了,你才有可能看到希望的光芒。Java 多线程优化与测试,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

耗时对比

t1: 耗时: 885739
t2: 耗时: 58548 | 耗时: 39284 | 耗时: 37096
t2_1: 耗时: 46900 | 耗时: 42319 | 耗时: 32841
t3: 耗时: 63848 | 耗时: 64668 | 耗时: 60082
t3_1: 耗时: 108355 | 耗时: 153665 | 耗时: 100006 

/**
     * 单线程
     */
    @Operation(summary = "单线程")
    @GetMapping("/t1")
    public AjaxResult<?> t1(){
        movieInformationUtil.main1();
        return AjaxResult.success();
    }

    /**
     * 多线程 使用切块分区使用多线程
     */
    @Operation(summary = "多线程 使用切块分区使用多线程")
    @GetMapping("/t2")
    public AjaxResult<?> t2(){
        movieInformationUtil.main2();
        return AjaxResult.success();
    }

    /**
     * 多线程 main2优化 使用批量插入
     */
    @Operation(summary = "多线程 main2优化 使用批量插入")
    @GetMapping("/t2_1")
    public AjaxResult<?> t2_1(){
        movieInformationUtil.main2_1();
        return AjaxResult.success();
    }

    /**
     * 多线程 可能会有遗漏 会有bug
     */
    @Operation(summary = "多线程 可能会有遗漏 会有bug")
    @GetMapping("/t3")
    public AjaxResult<?> t3(){
        movieInformationUtil.main3();
        return AjaxResult.success();
    }

    /**
     * 多线程 使用CountDownLatch等待全部线程执行完毕 解决main3遗漏问题
     */
    @Operation(summary = "多线程 使用CountDownLatch等待全部线程执行完毕 解决main3遗漏问题")
    @GetMapping("/t3_1")
    public AjaxResult<?> t3_1(){
        movieInformationUtil.main3_1();
        return AjaxResult.success();
    }

<!–多线程谷歌list分割–>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.0.0-jre</version>
</dependency>

package com.cn.crawlers.movieCrawler;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cn.domain.MovieInformation;
import com.cn.domain.MovieType;
import com.cn.service.MovieInformationService;
import com.cn.service.MovieTypeService;
import com.cn.utils.ImgUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
 
/**
     * 单线程
     */
    public void main1() {
        int[] i = {0};
        long l1 = System.currentTimeMillis();
        // 获取电影信息
        QueryWrapper<MovieInformation> informationQueryWrapper = new QueryWrapper<>();
        List<MovieInformation> movieList = movieInformationService.list(informationQueryWrapper);

        for (MovieInformation item : movieList) {
            //String base64 = ImgUtil.imageToBase64(imgUrl);
            //item.setCoverUrlBase64(StringUtils.isBlank(base64) ? imgUrl : base64);
            try {
                Thread.sleep(10);
                item.setCoverUrlBase64(String.valueOf(System.currentTimeMillis()));
                movieInformationService.updateById(item);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            log.info("当前数量{},线程名称: {}", i[0]++, Thread.currentThread().getName());
        }

        long l2 = System.currentTimeMillis();
        long l = l2 - l1;
        System.out.println("耗时: " + l);
    }

    /**
     * 多线程 使用切块分区使用多线程
     */
    public void main2() {
        int[] i = {0};
        long l1 = System.currentTimeMillis();
        // 获取电影信息
        QueryWrapper<MovieInformation> informationQueryWrapper = new QueryWrapper<>();
        List<MovieInformation> movieList = movieInformationService.list(informationQueryWrapper);

        // 获取分区大小
        List<List<MovieInformation>> partition = Lists.partition(movieList, movieList.size() / 20);

        // 创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(partition.size());
        CountDownLatch countDownLatch = new CountDownLatch(partition.size());

        for (List<MovieInformation> items : partition) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    for (MovieInformation item : items) {
                        String imgUrl = item.getCoverUrl();
                        try {
                            Thread.sleep(10);
                            item.setCoverUrlBase64(String.valueOf(System.currentTimeMillis()));
                            movieInformationService.updateById(item);
                            log.info("当前数量{},线程名称: {}", i[0]++, Thread.currentThread().getName());
                        } catch (Exception e) {
                            log.error("出bug了 -- {}", imgUrl);
                        }
                    }
                    countDownLatch.countDown();
                }
            });
        }

        // 等待所有的线程执行完毕
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        // 关闭线程池
        executorService.shutdown();
        long l2 = System.currentTimeMillis();
        long l = l2 - l1;
        System.out.println("耗时: " + l);
    }

    /**
     * 多线程 main2优化 使用批量插入
     */
    public void main2_1() {
        int[] i = {0};
        long l1 = System.currentTimeMillis();
        // 获取电影信息
        QueryWrapper<MovieInformation> informationQueryWrapper = new QueryWrapper<>();
        List<MovieInformation> movieList = movieInformationService.list(informationQueryWrapper);

        // 获取分区大小
        List<List<MovieInformation>> partition = Lists.partition(movieList, movieList.size() / 20);

        // 创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(partition.size());
        CountDownLatch countDownLatch = new CountDownLatch(partition.size());

        for (List<MovieInformation> items : partition) {
            executorService.execute(new Runnable() {
                List<MovieInformation> addList = new ArrayList<>();

                @Override
                public void run() {
                    for (MovieInformation item : items) {
                        String imgUrl = item.getCoverUrl();
                        try {
                            Thread.sleep(10);
                            item.setCoverUrlBase64(String.valueOf(System.currentTimeMillis()));
                            addList.add(item);
                            log.info("当前数量{},线程名称: {}", i[0]++, Thread.currentThread().getName());
                        } catch (Exception e) {
                            log.error("出bug了 -- {}", imgUrl);
                        }
                    }
                    log.info("SQL更新了,更新数量{}", addList.size());
                    movieInformationService.updateBatchById(addList);
                    countDownLatch.countDown();
                }
            });
        }

        // 等待所有的线程执行完毕
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        // 关闭线程池
        executorService.shutdown();
        long l2 = System.currentTimeMillis();
        long l = l2 - l1;
        System.out.println("耗时: " + l);
    }


    /**
     * 多线程 可能会有遗漏 会有bug
     */
    public void main3() {
        int[] i = {0};
        long l1 = System.currentTimeMillis();
        // 获取电影信息
        QueryWrapper<MovieInformation> informationQueryWrapper = new QueryWrapper<>();
        List<MovieInformation> movieList = movieInformationService.list(informationQueryWrapper);

        // 创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(20);

        List<Future<MovieInformation>> futures = new ArrayList<>();

        try {
            // 提交所有任务,并获取所有任务的执行结果
            for (MovieInformation item : movieList) {
                Future<MovieInformation> submit = executorService.submit(() -> {
                    Thread.sleep(10);
                    item.setCoverUrlBase64(String.valueOf(System.currentTimeMillis()));
                    log.info("当前数量{},线程名称: {}", i[0]++, Thread.currentThread().getName());
                    return item;
                });
                futures.add(submit);
            }

            for (Future<MovieInformation> future : futures) {
                MovieInformation movieInformation = future.get();
                movieInformationService.updateById(movieInformation);
            }

        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }

        // 关闭线程池
        executorService.shutdown();
        long l2 = System.currentTimeMillis();
        long l = l2 - l1;
        System.out.println("耗时: " + l);
    }

    /**
     * 多线程 使用CountDownLatch等待全部线程执行完毕 解决main3遗漏问题
     */
    public void main3_1() {
        int[] i = {0};
        long l1 = System.currentTimeMillis();
        // 获取电影信息
        QueryWrapper<MovieInformation> informationQueryWrapper = new QueryWrapper<>();
        List<MovieInformation> movieList = movieInformationService.list(informationQueryWrapper);

        // 创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(20);

        List<Future<MovieInformation>> futures = new ArrayList<>();
        CountDownLatch countDownLatch = new CountDownLatch(movieList.size());

        try {
            // 提交所有任务,并获取所有任务的执行结果
            for (MovieInformation item : movieList) {
                Future<MovieInformation> submit = executorService.submit(() -> {
                    Thread.sleep(10);
                    item.setCoverUrlBase64(String.valueOf(System.currentTimeMillis()));
                    countDownLatch.countDown();
                    log.info("当前数量{},线程名称: {}", i[0]++, Thread.currentThread().getName());
                    return item;
                });
                futures.add(submit);
            }

            // 等待所有的线程执行完毕
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            for (Future<MovieInformation> future : futures) {
                MovieInformation movieInformation = future.get();
                movieInformationService.updateById(movieInformation);
            }

        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }

        // 关闭线程池
        executorService.shutdown();
        long l2 = System.currentTimeMillis();
        long l = l2 - l1;
        System.out.println("耗时: " + l);
    }

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/192747.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!