您的位置:首页 > 教育 > 锐评 > 每日一学(4)

每日一学(4)

2024/10/6 0:28:49 来源:https://blog.csdn.net/w12345ll/article/details/140054948  浏览:    关键词:每日一学(4)

目录

1、线程状态的blocked 和 waiting 有什么区别

2、Runnable和Thread 区别

3、ConcurrentHashMap 线程的size方法 是不是安全的

4、DCL单例模式设计为什么需要volatile修饰实例对象

5、如果一个线程两次调用start 方法会有什么问题

6、java官方提供了几种线程池


1、线程状态的blocked 和 waiting 有什么区别

        都属于线程的阻塞等待状态

        blocked是指线程在等待监视器锁的时候的一个阻塞状态,多个线程在竞争synchronized,没有竞争到锁资源的线程,会被阻塞等待,这个时候线程状态叫blocked

        在线程整个生命周期里面,只有synchronized同步锁等待才会有这个blocked状态

        waiting 表示线程的等待状态, 需要有特定的方法来唤醒,比如 object.notify可以唤醒object.wait 方法

        blocked 和waiting 最大区别:

        1、blocked 是锁竞争失败后被动触发的状态,waiting人为触发的状态

        2、blocked的唤醒时自动触发的 waiting 必须要通过特定方法来主动唤醒

2、Runnable和Thread 区别

  1. Thread是个类 只能单一继承 ,Runnable是接口可以支撑多继承
  2. Runnable表示一个线程的顶级接口,Thread类是实现runnable
  3. Runnable 是一个任务 Thread才是真正处理的线程,前者去定义任务,后者去处理
  4. Thread真正意义上的线程实现 Runnable表示要求执行的一个任务

Thread和Runnable的实质是继承关系,没有可比性。无论使用Runnable还是Thread,都会new Thread,然后执行run方法。用法上,如果有复杂的线程操作需求,那就选择继承Thread,如果只是简单的执行一个任务,那就实现runnable

3、ConcurrentHashMap 线程的size方法 是不是安全的

本身的实现是线程安全的,调用size 获取元素个数的时候,是一个非线程安全的,当有线程调用put 方法去添加元素的时候,其他线程调用size 获取元素个数和实际存储元素个数是不一致的, 原因:size 是一个非线程同步的方法,put 和size 之间没有实现同步锁,

ConcurrentHashMap 数组累加2个方案:

1、当线程竞争不激烈,直接采用cas方式来实现原子个数的递增。

2、竞争激烈,使用数组来维护元素个数,直接在数组中随机取一个数,再通过cas实现递增

4、DCL单例模式设计为什么需要volatile修饰实例对象

DCL问题是在基于双重检查锁的设计下,单例模式中存在不完整的对象问题,本质是由于指令重排序导致的。 解决:在 instance变量增加一个volatile关键字进行修饰, 底层使用了内存屏障机制 避免指令重排序.

在单例模式的双重检查锁定(double-checked locking)实现中,如果不使用 volatile,可能会出现以下情况:构造函数中的初始化代码在分配内存给实例对象之后但在完全初始化之前被其他线程看到。这可能导致其他线程看到一个部分初始化的对象,从而引发错误。通过使用 volatile,我们可以防止这种指令重排,确保在对象被分配内存并初始化完成之前,其他线程不会看到这个对象

5、如果一个线程两次调用start 方法会有什么问题

在Java中,如果一个线程对象两次调用其start()方法,将会抛出IllegalThreadStateException。这是因为每个线程只能被启动(start)一次。一旦线程启动,它的执行状态就从NEW变为RUNNABLE(或BLOCKED,如果它试图获取一个锁但无法立即获得),并且此后不能再次更改为NEW状态来允许再次调用start()方法。

一个线程本身具备一个生命周期,包括6种状态

  1. NEW 线程创建好还没有调用start
  2. RUNNABLE 这个状态有可能正运行、可能等待就绪
  3. BLOCKED 处于锁等待
  4. WAITING 条件等待状态 触发条件唤醒 notify /wait
  5. TIMED_WAITINGWAITING 状态相同 多了一个超时条件触发
  6. TERMINATED 线程执行结束

当我们第一次调用start 方法。线程状态可能处于终止状态或者 非new 下的其他状态,在调用一次start 相当于让正在运行的线程重新运行一遍,是不合理的,为了避免这个问题,在线线程运行的时候先会判断线程的运行状态

6、java官方提供了几种线程池

jdk默认提供了5种线程池

        1、CachedThreadPool 可以缓存的线程池,可以用来处理大量短期的突发流量。最大线程数量为Integer.MAX_VALUE、 线程存活60秒、阻塞队列 SynchronousQueue

        2、FixedThreadPool 固定线程数量的线程池。核心线程和最大线程数量都是一个固定值,如果任务比较多处理不过来,就会加入到阻塞队列里面等待

        3、SingleThreadExecutor 只有一个工作线程的线程池,线程数量无法动态更改

        4、ScheduledThreadPool具有延迟执行功能的线程池,用来实现定时调度

        5、WorkStealingPool java8里面加入的一个线程池,内利用工作窃取的算法并行处理请求

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com