美文网首页
kotlin版对象复用池

kotlin版对象复用池

作者: 陆元伟 | 来源:发表于2021-08-13 16:05 被阅读0次

项目中经常用到对象池复用,但是不一样的对象对应的复用池都不统一。想着能否有一个对象池,可以不用关心对象是啥,实现对象池的功能?
对象池的功能需要支持:

  1. 不关系对象是什么,都能复用。
  2. 如何生产对象?
  3. 如何回收对象?

对于问题点 1 可以借助泛型和集合来实现。本来想参考Message来实现,但是没法给对象动态添加一个next属性,因此用一个集合来保存
对于问题点 2,如果我们复用集合里面有,直接返回集合里面的,如果没有,我们要实现化一个对象返回,但是有不知道他是什么类型,首先想到的是传个Class进来,这样我们就可以反射实例化一个对象
对于问题点3,所谓回收对象,就是把对象的属性都赋默默认值,然后把该对象存入集合。对象属性赋默认值也可以反射实现

对于第二点反射实例化一个对象,因为对象可能有多个构造器。而我们又不知道调用者到底要实例化哪一个,因此从所有构造器中选第一个实例化。为了给调用灵活性,这里我们添加一个factory给调用者自己决定是否要实例化一个对象。如果调用者自己创建了,就直接返回
上代码

class AnyPool<T>(private val clazz: Class<T>) {
    companion object{
      //方便调用者生成一个AnyPool对象
       inline fun <reified T> getAnyPool():AnyPool<T>{
            return AnyPool(T::class.java)
        }
    }
    //复用池
    private val nodes = mutableListOf<T>()
    //从复用池拿,如果复用池没有,先从factory创建,如果factory没有,则反射生成一个
    fun getFromPool(factory: () -> T? = { null }): T {
        if (nodes.isEmpty()) {
            println("from create")
            return factory() ?: let {
                val constructor = clazz.constructors[0]
                val parameters = constructor.parameters
                val params = arrayOfNulls<Any?>(parameters.size)
                parameters.forEachIndexed { index, parameter ->
                    params[index] = parameter.type.getDefault()
                }
                constructor.newInstance(*params) as T
            }


        }
        println("form pool")
        return nodes.removeAt(0)
    }
    //回收该对象到复用池
    fun recycle(node:T){
        node.clearField()
        nodes+=node
    }
    private  fun <K> Class<K>.getDefault():K?{
        return when(this){
             Int::class.java->0 as K
            Boolean::class.java->false as K
            Float::class.java->0f as K
            Double::class.java->0.0 as K
            Long::class.java->0L as K
            Short::class.java->0 as K
            Char::class.java->'0' as K
            Byte::class.java->0 as K
            else -> null
        }
    }
  //将该对象属性赋默认值
    private fun T.clearField(){
        (clazz.declaredFields+clazz.fields).forEach {field->
            field.isAccessible = true
            field.set(this,field.type.getDefault())
        }
    }

}

测试代码

data class Bean (var age:Int,var name:String?,var bean: Bean?)
fun testAnyPool(){
        val anyPool = AnyPool.getAnyPool<Bean>()
        val list = mutableListOf<Bean>()
        val test = Bean(11,"222",null)
       for (i in 0..4){
            val  bean = when {
               i%2==0-> anyPool.getFromPool {
                    Bean(i, "我是工厂创建的", test)
                }
                else ->{
                    anyPool.getFromPool()
                }
            }
            bean.age = i
            bean.bean = test
            list+=bean
            println(bean)
        }
        list.forEach {
            anyPool.recycle(it)
        }
        for (i in 1..5){
            println(anyPool.getFromPool())
        }
    }

输出,可以看到很好的满足了对象池的功能

from create
Bean(age=0, name=我是工厂创建的, bean=Bean(age=11, name=222, bean=null))
from create
Bean(age=1, name=null, bean=Bean(age=11, name=222, bean=null))
from create
Bean(age=2, name=我是工厂创建的, bean=Bean(age=11, name=222, bean=null))
from create
Bean(age=3, name=null, bean=Bean(age=11, name=222, bean=null))
from create
Bean(age=4, name=我是工厂创建的, bean=Bean(age=11, name=222, bean=null))
form pool
Bean(age=0, name=null, bean=null)
form pool
Bean(age=0, name=null, bean=null)
form pool
Bean(age=0, name=null, bean=null)
form pool
Bean(age=0, name=null, bean=null)
form pool
Bean(age=0, name=null, bean=null)

Process finished with exit code 0

相关文章

  • kotlin版对象复用池

    项目中经常用到对象池复用,但是不一样的对象对应的复用池都不统一。想着能否有一个对象池,可以不用关心对象是啥,实现对...

  • Java线程池

    为什么需要线程池 对象复用思想在编程中有很多应用,不论是线程池还是连接池都是一种对象复用的思想。今天来谈谈Java...

  • Netty对象池

    在平时工作中,听说和使用过连接池,线程池等.还有一种就是对象池,可以实现对象复用的功能. 当然实现对象池的方式手段...

  • 享元模式

    简介 缓存共享对象,复用共享对象,比如各种池化操作,数据库连接池缓存连接,线程池缓存线程等等。 享元模式样...

  • GenericObjectPool对象池实战

    通常一个对象创建/销毁的时候非常耗时,我们不会频繁的创建销毁它,而是考虑复用。复用对象的一种做法就是对象池,将创建...

  • 深度剖析 C++ 对象池自动回收技术实现

    对象池可以显著提高性能,如果一个对象的创建非常耗时或非常昂贵,频繁去创建的话会非常低效。对象池通过对象复用的方式来...

  • 你使用对象池了吗

    什么是对象池?对象池,简单的说就是一种为了避免重复创建,删除对象的解决方案。它可以通过复用游戏对象,一定程度上提高...

  • 数据库连接池、线程池等管理的关键点,你知道吗?

    在Java应用开发中经常会用到连接池、线程池等池化技术。池化(pool)技术的本质是通过复用对象、连接等资源,减少...

  • Netty的内存使用方法与原理——池化与堆外内存的开启与关闭

    一、内存池的选择 1.Netty为什么要使用内存池? 创建对象开销大 对象高频率创建且可复用 支持并发又能保护系统...

  • Eevee框架4——对象池

    这里先简述一下对象池的目的以及什么情况下需要对象池: 将部分需要持续性复用的物体(或对象)以隐藏/修改位置等方式先...

网友评论

      本文标题:kotlin版对象复用池

      本文链接:https://www.haomeiwen.com/subject/gzadbltx.html