线程的4种创建方式,线程池7大参数

线程的四种创建方式

1.继承Thread类
public static class Thread01 extends Thread {
    @Override
    public void run() {
        System.out.println("执行线程-------------------------01");
    }
}

Thread01 thread01 = new Thread01();
thread01.start();
2.实现Runnable接口
public static class Thread02 implements Runnable {
    @Override
    public void run() {
        System.out.println("执行线程-------------------------02");
    }
}
Thread thread02 = new Thread(new Thread02());
thread02.start();
3.实现Callable接口
public static class Thread03 implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        System.out.println("执行线程-------------------------03");
        return 3;
    }
}
FutureFask futureFask = new FutureFask(new Thread03());
Thread thread03 = new Thread(futureFask);
thread03.start()
4.线程池
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.submit(thread02);
executorService.execute(futureTask);

线程池的7大参数

1.参数列表
  1. corePoolSize核心线程数(一直存在),线程池创建好以后就准备就绪执行的数量

  2. maximumPoolSize最大线程数量,控制资源

  3. keepAliveTime存活时间,当前正在运行的线程数量>核心数量时,空闲线程等待的最大时间

    释放空闲线程(maximumPoolSize - corePoolSize)

  4. unit 时间单位

  5. workQueue阻塞队列,如果任务很多,就会将目前多的任务放在队列里面。只要有线程空闲了,就会去队列里面取出新的任务执行。

  6. threadFactory线程的创建工厂

  7. handler处理队列满了的情况,就按照拒绝策略执行拒绝任务

2.工作顺序
  1. 线程池创建,准备好core数量的核心线程,准备接受任务

  2. core满了,就将再进来的任务放入阻塞队列中,空闲的core就会自己去阻塞队列获取执行任务

  3. 阻塞队列满了,就直接开启新线程执行,最大只能开到max指定的数量

  4. max满了就用拒绝策略,执行拒绝任务

  5. max都执行完成,有很多空闲,在指定的存活时间以后,释放max-core这些线程

3.Executors类创建线程
Executors.newCachedThreadPool();
Executors.newFixedThreadPool();

如何正确配置线程池参数

1、首先为什么不推荐使用Executors类默认的创建线程池方法。

因为太耗费资源了,默认的创建参数不是coreSize太多,就是Queue太大,实际上很多资源都是空闲的。我们应该贴合自己的业务场景,创建合适大小的线程池。

2、当线程数过多时会增加上下文切换的成本。什么是上下文切换?

我们的CPU有一个核心个数(也就是我们俗称的几核CPU),任何一个CPU在同一时间只能在一个线程上面调度。比如说我们的餐馆点菜,10个桌子的客人(10个线程),只有7个服务员(7个CPU核心),那么必定有3个桌子是空闲的,服务员切换桌子的场景就是我们的CPU调度。切换的时候我们CPU会保存当前线程的一些状态信息,以便下次切换回来能够回到当前的执行状态,而线程数一但大了起来,我们的CPU会频繁的切换上下文,这其中需要耗费大量的时间,所以线程数不宜过大。

而线程数过小的话,会导致我们有大量的任务堆积到线程队列里面,甚至导致OOM,CPU根本没得到充分利用。

3、有一个简单并且适用面比较广的公式:
  • CPU 密集型任务(N+1): 这种任务消耗的主要是 CPU 资源,可以将线程数设置为 N(CPU 核心数)+1,比 CPU 核心数多出来的一个线程是为了防止线程偶发的缺页中断,或者其它原因导致的任务暂停而带来的影响。
  • I/O 密集型任务(2N): 这种任务应用起来,系统会用大部分的时间来处理 I/O 交互,而线程在处理 I/O 的时间段内不会占用 CPU 来处理,这时就可以将 CPU 交出给其它线程使用。因此在 I/O 密集型任务的应用中,我们可以多配置一些线程,具体的计算方法是 2N。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值