Java 多线程优化与测试

耗时对比

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);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值