多线程批量插入数据

1.多线程实现方式

  1. 继承Thread类, 重写run方法,run里面的代码就是我们开启多线程会执行的业务逻辑
/**
 * 继承Thread, 重写run方法
 */
public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 2000; i++) {
            System.out.println(Thread.currentThread().getName()+": "+i);
        }
    }
}
public class Demo {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        // start()方法,开辟一个线程内存, 在myThread线程里运行run方法
        myThread.start();
        for (int i = 0; i < 2000; i++) {
            System.out.println(Thread.currentThread().getName()+": "+i);
        }
    }
}

在这里插入图片描述

2.实现runable接口, 重写run方法

public class MyRunable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 2000; i++) {
            System.out.println(Thread.currentThread().getName()+": "+i);
        }
    }
}
public class Demo {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        // start()方法,开辟一个线程内存, 在myThread线程里运行run方法
        myThread.start();
        for (int i = 0; i < 2000; i++) {
            System.out.println(Thread.currentThread().getName()+": "+i);
        }

        MyRunable myRunable = new MyRunable();
        Thread thread = new Thread(myRunable,"实现runable");
        thread.start();
    }
}

在这里插入图片描述
3.实现Callable接口, 重写run方法

public class MyCallable implements Callable {

    @Override
    public List<String> call() throws Exception {
        List<String> list =new ArrayList<String>();
        for (int i = 0; i < 2000; i++) {
            // 往集合里添加2000个元素
            list.add("添加"+i);
        }
        // 执行完2000次,返回个集合
        return list;
    }
}
public class Demo {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        // start()方法,开辟一个线程内存, 在myThread线程里运行run方法
        myThread.start();
        for (int i = 0; i < 2000; i++) {
            System.out.println(Thread.currentThread().getName()+": "+i);
        }

        MyRunable myRunable = new MyRunable();
        Thread thread = new Thread(myRunable,"实现runable");
        thread.start();

        MyCallable myCallable = new MyCallable();
        FutureTask<Callable> futureTask = new FutureTask<Callable>(myCallable);
        new Thread(futureTask).start();

        List result = new ArrayList();
        //这边获取callable里返回的数据会有异常,需要捕获
        try {
            result = (List) futureTask.get();
        } catch (Exception e) {
            e.printStackTrace();
        }

        for (Object o : result) {
            System.out.println(o);
        }
    }
}

以上三种是线程的三种基本实现方式

2.利用线程池实现多线程

线程池的实现方式有很多,例如:
  1. Executors.newFixedThreadPool(5)     开启固定线程池,分配5个线程

在这里插入图片描述
2.CachedThreadPool 可缓存的线程池
3.ScheduledThreadPoolExecutor 支持定时及周期性任务执行
4.ThreadPoolExecutor 可根据实际需要配置的线程池

使用ThreadPoolExecutor批量分段插入100W数据:

public void insertThreadData() {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                CORE_POOL_SIZE,
                MAX_POOL_SIZE,
                KEEP_ALIVE_TIME,
                TimeUnit.SECONDS,
                //1. 如果没有空闲的线程执行该任务且当前的线程数等于corePoolSize同时阻塞队列未满,
                //   则将任务入队列,而不添加新的线程。
                //2. 如果没有空闲的线程执行该任务 且阻塞队列已满同时池中的线程数小于maximumPoolSize,
                //   则创建新的线程执行任务。
                new ArrayBlockingQueue<>(QUEUE_CAPACITY),
                //在任务被拒绝添加后,会在调用execute方法的的线程来执行被拒绝的任务,除非线程被关闭
                new ThreadPoolExecutor.CallerRunsPolicy());

        List<Long> ids = new ArrayList<>();
        for (int i = 1; i <= 1000000; i++) {
            String id = idWorker.nextId();
            ids.add(Long.parseLong(id));
        }

        for (int i = 1; i <= 25; i++) {
            // 多线程查询, 传入当前页和显示条数, 需要把已经注入的mapper映射传入到run里,这样才不会为null
            InsertRunable runable = new InsertRunable(i, threadUserMapper, i * 40000, (i - 1) * 40000, ids);
            //提交任务到线程池, submit,不会抛出异常而是把异常保存在成员变量中,在FutureTask.get阻塞获取的时候再把异常抛出来
//            executor.submit(runable);  有返回值

            // execute直接抛出异常之后线程就死掉了, 没有返回值
            executor.execute(runable);
        }

        //关闭线程池
        executor.shutdown();
    }
public class InsertRunable implements Runnable {

    private int num;

    private int endIndex;

    private int startIndex;
    private ThreadUserMapper threadUserMapper;
    private UserService userService;
    private List<Long> ids;


    public InsertRunable(){

    }
    // 至少num至少从1开始
    public InsertRunable(int num,ThreadUserMapper threadUserMapper, int endIndex, int startIndex, List<Long> ids){
        this.endIndex=endIndex;
        this.startIndex=startIndex;
        this.threadUserMapper = threadUserMapper;
        this.userService= new UserService();
        this.ids = ids;
        this.num = num;
    }

    @Override
    public void run() {
        Long startTime = System.currentTimeMillis();
        ThreadUser threadUser = new ThreadUser();
        for (int i = startIndex; i < endIndex;i++) {
           userService.insert(i,threadUserMapper,ids.get(i));
//            System.out.println(i);
        }

        Long endTime = System.currentTimeMillis();
        System.out.println("完成第"+num+"次4W数据插入,花费: "+(endTime-startTime)/1000+"s");
    }
}
public void insert(int startIndex, ThreadUserMapper userMapper, Long id) {
        ThreadUser threadUser = new ThreadUser();
        //循环遍历 20W
        threadUser.setId(id);
        threadUser.setUsername(String.valueOf(startIndex));
        threadUser.setPassword(String.valueOf(startIndex));
        userMapper.insert(threadUser);
    }
  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值