1.为什么不推荐通过Executors直接创建线程池呢(https://blog.csdn.net/zzhongcy/article/details/130323412)
【强制】线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明:Executors各个方法的弊端:
1) newFixedThreadPool和newSingleThreadExecutor: 主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM(内存溢出)。
2) newCachedThreadPool和newScheduledThreadPool: 主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。
总结:
newFixedThreadPool()、newSingleThreadExecutor() 底层代码 中 LinkedBlockingQueue 没有设置容量大小,默认是 Integer.MAX_VALUE, 可以认为是无界的。线程池中 多余的线程会被缓存到 LinkedBlockingQueue中,最终内存撑爆。
Executors.newCachedThreadPool()
优缺点:
优点: 很灵活,弹性的线程池线程管理,用多少线程给多大的线程池,不用后及时回收,用则新建 ;
缺点: 从源码中可以看出,SynchronousQueue() 只能存一个队列,可以认为所有 放到 newCachedThreadPool() 中的线程,不会缓存到队列中,而是直接运行的, 由于最大线程数是 Integer.MAX_VALUE ,这个数量级可以认为是无限大了, 随着执行线程数量的增多 和 线程没有及时结束,最终会将内存撑爆。
总结:
newCachedThreadPool()、newScheduledThreadPool() 的 底层代码 中 的 最大线程数(maximumPoolSize) 是 Integer.MAX_VALUE,可以认为是无限大,如果线程池中,执行中的线程没有及时结束,并且不断地有线程加入并执行,最终会将内存撑爆。
创建线程 或 线程池时请指定有意义的线程名称,方便出错时回溯(这个不是重点)
2.线程池有哪几种状态?每种状态分别表示什么?(https://blog.csdn.net/wufaqidong1/article/details/123724222)
在 Java 中,线程池的状态和线程的状态是完全不同的,线程有 6 种状态:NEW:初始化状态、RUNNABLE:可运行/运行状态、BLOCKED:阻塞状态、WAITING:无时限等待状态(超时等待)、TIMED_WAITING:有时限等待状态和 TERMINATED:终止状态(线程的状态通常有五种:创建、就绪、运行、阻塞、死亡)。而线程池的状态有以下 5 种:
RUNNING:运行状态,线程池创建好之后就会进入此状态,如果不手动调用关闭方法,那么线程池在整个程序运行期间都是此状态。
SHUTDOWN:关闭状态,不再接受新任务提交,但是会将已保存在任务队列中的任务处理完。
STOP:停止状态,不再接受新任务提交,并且会中断当前正在执行的任务、放弃任务队列中已有的任务。
TIDYING:整理状态,所有的任务都执行完毕后(也包括任务队列中的任务执行完),当前线程池中的活动线程数降为 0 时的状态。到此状态之后,会调用线程池的 terminated() 方法,此方法留给用户自己实现。
TERMINATED:销毁状态,当执行完线程池的 terminated() 方法之后就会变为此状态。
3.Sychronized和ReentrantLock有哪些不同点?(https://blog.csdn.net/qq_19667981/article/details/124652865)
①ReentrantLock显示地获得,释放锁,synchronized隐式获得释放锁
②ReentrantLock可响应中断,可轮回,synchronized是不可以响应中断的
③ReentrantLock是API级别的,synchronized是JVM级别的
④ReentrantLock可以实现公平锁或非公平锁,synchronized仅可实现非公平锁
⑤ReentrantLock通过Condition可以绑定多个条件
⑥底层实现不一样,synchronized是同步阻塞,使用的是悲观并发策略,lock是同步非阻塞,采用的是乐观并发策略。
⑦Lock是一个接口,而synchronized是java中的关键字,synchronized是内置的语言实现
⑧synchronized 在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而 Lock 在发生异常时,如果没有主动通过 unLock()去释放锁,则很可能造成死锁现象, 因此使用 Lock 时需要在 finally 块中释放锁。
网友评论