java 多线程的简单使用

java 多线程的用处,如异步处理,多线程同步数据等
通常我们的做法是使用Executors来创建线程池,因为他可以做到统一管理,有效的控制最大并发线程防止new Thread() 产生的线程恶性竞争等问题;

Executors 的4 种线程池

创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
newFixedThreadPool

创建一个可缓存线程池,应用中存在的线程数可以无限大
newCachedThreadPool

创建一个定长线程池,支持定时及周期性任务执行
newScheduledThreadPool

创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
newSingleThreadExecutor

下面使用定长线程池同步一万条数据:

/**
 * @version 1.0
 * @author: lsy
 * @create: 2021-06-01 11:19
 **/
public class ThreadTest {

	//每个线程分配的数据量
    private static final Integer VALUE = 1000;

    /**
     * 这里我们使用固定线程数的线程池同步数据
     * 举例生成一万条数据,分给5个线程,每个线程处理1000条数据
     * 线程全部使用时则等待
     *
     * @param args
     */
    public static void main(String[] args) {

        //创建一万条测试数据
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            list.add("测试数据" + i);
        }


        //创建线程池(固定线程数=5)
        ExecutorService executor = Executors.newFixedThreadPool(5);
        int formIndex = 0; //切割list的fromIndex
        while (true) {
            //切割list 的toIndex (如果toIndex值没有超过list的总大小,则使用list的size)
            int toIndex = Math.min((formIndex + VALUE), list.size());
            List<String> strings = list.subList(formIndex, toIndex);
            //如果线程没有关闭
            if (!executor.isShutdown()) {
                executor.execute(runnable(strings));
            }
            //下一次的 结束值值=本次的开始值
            formIndex = toIndex;
            if (formIndex >= list.size()) {
                break;
            }
        }
        //关闭线程池
        executor.shutdown();
    }

    /**
     * 进入线程方法
     *
     * @param list
     * @return
     */
    public static Runnable runnable(List list) {
        return new Runnable() {
            @Override
            public void run() {
                insert(list);
            }
        };
    }

    /**
     * 入库方法
     *
     * @param list
     */
    private static void insert(List list) {
        for (int i = 0; i < list.size(); i++) {
            String o = (String) list.get(i);
            System.out.println(o);
        }
    }

}

在实际项目中通常线程类已经设置好,比如核心线程数,最大线程数,线程阻塞策略等

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;


@EnableAsync
@Configuration
public class ThreadPoolConfig {

	private static Logger log = LoggerFactory.getLogger(ThreadPoolConfig.class); 
    /***
     * 重要任务执行
     * Date 2021/6/8 14:15
     * @author lsy
     * @param []
     * @return java.util.concurrent.Executor
     */
    @Bean("timingPool")
    public Executor getTimingPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //设置线程的核心线程数 (读取cpu核心,使用cpu核心个数作为线程数)
        executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
        //设置线程最大线程数 (读取cpu核心,使用cpu核心数*2作为最大线程数)
        executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 2);
        // use SynchronousQueue
        //设置阻塞队列的容量 (不使用阻塞队列)
        executor.setQueueCapacity(0);
        // 设置线程池允许的空闲时间(默认为60秒)
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("timingPool-");
        executor.setRejectedExecutionHandler((r, e) -> {
            log.warn("timing pool can't schedule job immediately, maybe some job using too much cpu times.");
            // 定时任务优先级较高,不惜一些代价都需要继续执行,开线程继续干~
            new Thread(r).start();
        });
        return executor;
    }


    /***
     * 普通任务执行
     * Date 2021/6/8 14:15
     * @author lsy
     * @param []
     * @return java.util.concurrent.Executor
     */
    @Bean("commonPool")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //设置线程的核心线程数 (读取cpu核心,使用cpu核心个数作为线程数)
        executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
        //设置线程最大线程数 (读取cpu核心,使用cpu核心个数作为线程数)
        executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors());
        //设置阻塞队列的容量
        executor.setQueueCapacity(1024);
        // 设置线程池允许的空闲时间(默认为60秒)
        executor.setKeepAliveSeconds(180);
        executor.setThreadNamePrefix("commonPool-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }

直接注入使用就好

    @Resource(name = "commonPool")
    private Executor commonPool;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值