线程池简介

线程池的重要性

 

什么是池?

软件中的池,可以理解为计划经济

为什么使用线程池?

1.反复创建线程开销大

2.过多的线程会占用太多的内存

用少量的线程——避免内存占用过多

让这部分线程都保持工作,且可以反复执行任务——避免生命周期的损耗

应用场合

创建和停止线程池

线程池构造方法的参数

 

添加线程的规则

 

增减线程的特点

 

工作队列

常见的队列类型

1.直接交接:SynchronousQueue

2.无界队列:LinkedBlockingQueue

3.有界队列:ArrayBlockingQueue

4.延迟队列:DelayedWorkQueue

线程池手动创建还是自动创建

自动创建(即直接调用JDK封装好的构造方法)

1.newFixedThreadPool

package threadpool;
​
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
​
/**
 *  演示newFixedThreadPool
 *  固定的线程数
 */
public class FixedThreadPoolTest {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(4);
        for (int i = 0; 0 < 1000 ;
        i++){
            executorService.execute(new Task());
        }
    }
​
​
}
// 任务类
class Task implements Runnable{
    @Override
    public void run() {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName());
    }
}
​

弊端:超出工作队列,内存溢出

2.newSingleThreadExecutor

package threadpool;
​
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
​
/**
 * 演示newSingleThreadExecutor
 * 只有一个线程
 */
public class SingleThreadExecutor {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 1000; i++) {
            executorService.execute(new Task());
        }
    }
}
​
​

弊端:当请求堆积,占用大量内存

3.CachedThreadPool

可缓存线程池

特点:具有自动回收多余线程的功能

package threadpool;
​
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
​
/**
 * 演示newCachedThreadPool
 * 可缓存线程
 */
public class CachedThreadPool {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 1000; i++) {
            executorService.execute(new Task());
        }
    }
}
​
​

 

4.ScheduledThreadPool

支持定时及周期性任务执行的线程池

package threadpool;
​
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
​
/**
 * 演示newScheduledThreadPool
 * 周期性任务执行的线程池
 */
public class ScheduledThreadPoolTest {
    public static void main(String[] args) {
        ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(10);
      // 延迟5秒
              //threadPool.schedule(new Task(), 5, TimeUnit.SECONDS);
      //以一定频率
       threadPool.scheduleAtFixedRate(new Task(), 1, 3, TimeUnit.SECONDS);
    }
}
​
​

5.workStealingPool是JDK1.8加入的

  • 这个线程池和之前的都有很大不同

  • 子任务

  • 窃取,每个线程之前可以合作

4种线程池的构造方法的参数

 

正确创建线程池的方法

根据不同的业务场景,设置线程池参数

比如:内存有多大,给线程取什么名字等等

线程池里的线程数量多少合适

 

停止线程池的正确方法

1、shutdown

并不会马上停止,把之前的任务执行完毕后,才停止线程池

2、isShutdown

判断线程池是否进入停止状态

3、isTerminated

判断线程池是否完全终止

4、awaitTermination

用来判断

所有任务执行完毕

等待的时间到了

等待过程中被打断了,抛出异常

5、shutdownNow

立刻停止线程池,返回在任务队列未执行的任务集合

暂停和恢复线程池

任务太多怎么拒绝

 

4种拒绝策略

AbortPolicy

DiscardPolicy

DiscardOldestPolicy

CallerRunsPolicy

钩子方法

package threadpool;
​
import java.sql.Time;
import java.util.concurrent.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
​
/**
 * 手动创建线程池
 * 演示每个任务执行前后放钩子函数
 */
public class PauseableThreadPool extends ThreadPoolExecutor {
​
    private boolean isPaused;
    private final ReentrantLock lock = new ReentrantLock();
    private Condition unpaused = lock.newCondition();
​
    public PauseableThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }
​
    public PauseableThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
    }
​
    public PauseableThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
    }
​
    public PauseableThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    }
​
    // 钩子函数 执行任务之前检查
    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        super.beforeExecute(t, r);
        lock.lock();
        try {
            while (isPaused) {
                unpaused.await();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
​
    }
    
    // 暂停方法
    private void pause() {
        lock.lock();
        try {
            isPaused = true;
        } finally {
            lock.unlock();
        }
    }
    
    // 恢复方法
    public void resume() {
        lock.lock();
        try {
            isPaused = false;
            unpaused.signalAll();
        } finally {
            lock.unlock();
        }
    }
​
    public static void main(String[] args) throws InterruptedException {
        PauseableThreadPool pauseableThreadPool = new PauseableThreadPool(10, 20, 10L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
        // 匿名内部类    在创建实例的同时给出类的定义,所有这些在一个表达式中完成。
        Runnable runnable = new Runnable() {
​
            @Override
            public void run() {
                System.out.println("我被执行");
                try {
                    // 防止太快
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        for (int i = 0; i < 10000; i++) {
            pauseableThreadPool.execute(runnable);
        }
        Thread.sleep(1500);
        pauseableThreadPool.pause();
        System.out.println("线程池被暂停了");
        Thread.sleep(1500);
        pauseableThreadPool.resume();
        System.out.println("线程池被恢复了");
    }
​
}
​

使用线程池的注意点

  • 避免任务堆积

  • 避免线程数过度增加

  • 排查线程泄露

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值