Java进阶13 线程池

Java进阶13 线程池

一、线程生命周期

线程被创建并启动以后,它并不是一启动就进入了执行状态,也不是一直处于执行状态。线程对象在不同的时期有不同的状态,这各种状态就是线程的生命周期。

Java中的线程状态被定义在了java.lang.Thread.State枚举类

状态含义
NEW(新建)创建线程对象
RUNNABLE(就绪)start方法被调用,但是还没有抢到CPU执行权
BLOCKED(阻塞)线程开始运行,但是没有获取到锁对象
WAITING(等待)wait方法
TIMED-WAITING(计时等待)sleep方法
TERMINATED(结束状态)代码全部运行完毕

1、线程生命周期图

过程:创建(NEW)线程后调用start方法进入就绪(RUNNABLE)状态,如果该线程顺利抢到CPU执行权,就进入运行状态,运行主要执行run方法中的代码逻辑,如果运行期间没有被其他线程夺走CPU执行权,则该线程将一直运行至结束,结束后进入死亡(TERMINTATED)状态。但如果运行期间被其他线程抢走CPU执行权,该线程将回到就绪状态。此外,当其运行期间调用了sleep()方法,则会进入即计时等待(TIMED-WAITING)状态 ,指定的休眠时间到达后,自动转为就绪状态;如果调用了wait()方法,就会进入无限等待(WAITING)状态,需要其他线程调用notify()方法才能继续进入就绪状态;如果在运行期间无法获取到锁,就会进入阻塞(BLOCKED)状态,知道其他线程释放了锁,该线程才能获得锁,获得锁之后就会进入就绪状态。

二、线程池

将线程对象交给线程池维护,可以降低系统成本,从而提升程序的性能

2、使用JDK提供的线程池

方法说明
static ExecutorService newCachedThreadPool()创建一个默认的线程池
static newFixedThreadPool(int nThreads)创建一个指定最多线程数量的线程池

3、自定义线程池

ThreadPoolExecutor类

3.1 构造方法
ThreadPoolExecutor(int corePoolSize,int maxnumPoolSize,long keepActiveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)
  • 参数1:核心线程数量【不能小于0】

  • 参数2:最大线程数量(核心线程数+临时线程数)【不能小于等于0】

  • 参数3:空闲时间(数值)【不能小于0】

  • 参数4:时间单位【时间单位】

  • 参数5:任务队列【不能为null】

    • 有限队列 new ArrayBlockingQueue<>(队列长度)

    • 无限队列 new LinkedBlockingQueue<>()

  • 参数6:线程对象任务工厂【不能为null】

  • 参数7:拒绝策略【不能为null】

3.2 Demo
public class ThreadPoolDemo2 {
    public static void main(String[] args) {
        /*
            指定核心线程数为2,最大线程数为5,空闲时间为60秒,有限队列,线程任务工厂为指定默认的工厂,拒绝策略为AbortPolicy的自定义线程池;
        */
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                2,
                5,
                60,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(10),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
​
        for (int i = 1; i <= 16; i++) {
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+"提交了线程任务");
                }
            });
        }
    }
}
3.3 注意事项
  • Q:临时线程对象何时创建?

    A:提交的线程任务数量 > 核心线程数 + 任务队列数量

  • Q:什么时候会触发拒绝策略?

    A:提交的线程任务数量 > 最大线程数 + 任务队列数量

3.4 拒绝策略
策略选项说明
ThreadPoolExecutor.AbortPolicy丢弃任务并抛出RejectedExecutionException异常(默认)
ThreadPoolExecutor.DiscardPolicy丢弃任务,但是不抛出异常,这是不推荐的做法
ThreadPoolExecutor.DiscardOldestPolicy抛弃队列中等待最久的任务,然后把当前任务加入队列中
ThreadPoolExecutor.CallerRunPolicy调用任务的run()方法,绕过线程池直接执行

三、单例设计模式

单例指单个实例,保证类的对象在内存中只有一份

1、使用场景

如果创建一个对象需要消耗的资源过多,比如I/O与数据库的连接,并且这个对象完全是可以复用的,我们就可以考虑将其设计为单例的对象

2、设计模式

2.1 饿汉式
class Single {
    
     //1、私有构造方法,组织其他类创建本类对象
    private Single(){
    }
​
    //在本类中创建自己这个类的对象
    private static Single s = new Single();
​
​
    /**
     * 提供一个方法供外部获取本类单例对象
     * @return 返回单例对象
     */
    public static Single getInstance(){
        return s;
    }
}
2.2 懒汉式(延迟加载模式)
class Single {
    
     //1、私有构造方法,组织其他类创建本类对象
    private Single(){
    }
​
    //在本类中创建自己这个类的对象
    private static Single s = new Single();
​
​
    /**
     * 提供一个方法供外部获取本类单例对象
     * @return 返回单例对象
     */
    public static Single getInstance(){
        return s;
    }
}
  • 注意事项:双重检查锁是可以减少上锁次数,避免创建出多个对象造成效率浪费

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值