美文网首页
深入学习java笔记-18.JUC-线程池

深入学习java笔记-18.JUC-线程池

作者: 笨鸡 | 来源:发表于2019-05-14 11:08 被阅读0次

学习目的:看MySQL索引优化时,教程需要70万测试数据,我得写一个random加线程池批量导入,节省时间。

new Thread弊端

  • 每次new Thread 新建对象,性能差。
  • 线程缺乏统一管理,可能无限制的新建线程,互相竞争,有可能占用过多系统资源导致死机或OOM。
  • 缺少更多功能,如更多执行、定期执行、线程中断。

线程池的好处

  • 重用存在的线程,减少对象创建、消亡的开销,性能佳
  • 可有效控制最大并发线程数,提高系统资源利用率,同时可以避免过多资源竞争,避免阻塞
  • 提供定时执行、定期执行、单线程、并发数控制等功能

线程池-ThreadPoolExecutor

线程池内部属性

  • corePoolSize:核心线程数量
  • maximumPoolSize:线程最大线程数
  • workQueue:阻塞队列,存储等待执行的任务,很重要,会对线程池运行过程产生重大影响
  • keepAliveTime:线程没有任务执行时最多保持多久时间终止
  • unit:keepAliveTime的时间单位
  • threadFactory:线程工厂,用来创建线程
  • rejectHandler:当拒绝处理任务时的策略
线程池.png

线程池相关方法

  • execute():提交任务,交给线程池执行。
  • submit():提交任务,能够返回执行结果 execute+Future
  • shutdown():关闭线程池,等待任务都执行完
  • shutdownNow():关闭线程池,不等待任务执行完
  • getTaskCount():线程池已执行和未执行的任务总数
  • getCompletedTaskCount():已完成的任务数量
  • getPoolSize():线程池当前的线程数量
  • getActiveCount():当前线程池中正在执行任务的线程数量

线程池-Executor框架接口

  • Executors.newCachedThreadPool
package juc;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample1 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            int index = i;
            executorService.execute(()-> System.out.println("task:" + index));    //直接传i报错,提示需要一个final的数据,不太理解。
        }
        executorService.shutdown();
    }
}
  • Executors.newFixedThreadPool
package juc;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample2 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            int index = i;
            executorService.execute(()-> System.out.println("task:" + index));
        }
        executorService.shutdown();
    }
}
  • Executors.newSingleThreadExecutor
package juc;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample3 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            int index = i;
            executorService.execute(()-> System.out.println("task:" + index));
        }
        executorService.shutdown();
    }
}
  • Executors.newScheduledThreadPool
package juc;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ThreadPoolExample4 {
    public static void main(String[] args) {
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);
//        for (int i = 0; i < 10; i++) {
//            int index = i;
//            executorService.execute(()-> System.out.println("task:" + index));
//        }
//        executorService.schedule(() -> System.out.println("schedule run"), 3, TimeUnit.SECONDS);
        executorService.scheduleAtFixedRate(() -> System.out.println("scheduleAtFixedRate run"),
                1, 3, TimeUnit.SECONDS);
//        executorService.shutdown();
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("TimeTask Run");
            }
        }, new Date(), 2 * 1000);
    }
}
  • ThreadPoolExecutor
        StudentService studentService = ac.getBean(StudentService.class);
        int corePoolSize = 2;
        int maximumPoolSize = 16;
        long keepAliveTime = 30;
        TimeUnit unit = TimeUnit.SECONDS;
        LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(30);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                corePoolSize, maximumPoolSize, keepAliveTime,
                unit, workQueue, new ThreadPoolExecutor.CallerRunsPolicy());
        executor.prestartAllCoreThreads(); // 预启动所有核心线程
        for (int i = 0; i < 700000; i++) {
//            studentService.insertClass();
            executor.execute(()->studentService.insertClass());
        }
        // 线程池水深,我还得好好学习内部的参数配置与原理。

线程池-合理配置

  • CPU密集型任务,就需要尽量压榨CPU,参考值可以设为NCPU+1
  • IO密集型任务,参考值可以设置为2*NCPU

相关文章

网友评论

      本文标题:深入学习java笔记-18.JUC-线程池

      本文链接:https://www.haomeiwen.com/subject/kzojaqtx.html