Native Code To Gget Expensive Resource Such As Database Connection(Self Protection Mechanism)

本文介绍了一种资源池模型,用于在高并发场景中有效管理和保护系统资源,如数据库连接。通过动态代理创建资源实例,使用资源池类实现资源的获取和释放,确保在资源有限的情况下,线程能及时响应并避免长时间等待。
emm, in our common application scenario, getting system resource such as database connection seems to be easy , but when we program in high concurrent scenario , it would be disorder. How can we protect our rare and precious system resources? I think this model may help us:

ResourcePool -> the main Class

public class ResourcePool {

    private LinkedList<Resource> pool = new LinkedList<>();

    public ResourcePool(int initialSize) {
        if(initialSize > 0){
            for (int i = 0; i < initialSize; i++) {
                pool.addLast(ResourceDriver.createResource());
            }
        }
    }


    public void releaseResource(Resource resource){
        if(resource != null){
            synchronized (pool){ //after jdk 1.6 I prefer use synchronized to ConcurrentLinkedQueue
                pool.addLast(resource);
                pool.notifyAll();
            }
        }
    }

    public Resource fetchResource(long mills) throws InterruptedException {
        synchronized (pool){
            //full time out
            if(mills < 0){
                while(pool.isEmpty()){
                    pool.wait();
                }
                return pool.removeFirst();
            }else {
                long future = System.currentTimeMillis() + mills;
                long remaining = mills;
                while(pool.isEmpty() && remaining > 0){
                    pool.wait(remaining);
                    remaining = future - System.currentTimeMillis();
                }
                Resource resource = null;//you can implement a NullAble resources
                if(!pool.isEmpty())
                    resource = pool.removeFirst();
                return  resource;
            }

        }
    }


}

Class To Construct Resource : for convenienceuse, use dynamic proxy to construct resource instance
//in your code, you can implement your realistic service

mport java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.TimeUnit;

/**
 * Created by LY on 2018/11/30.
 */
public class ResourceDriver {

    static class ResourceHandler implements InvocationHandler{
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if(method.getName().equals("commit")){
                TimeUnit.MILLISECONDS.sleep(100);//mock do some service
            }
            return null;
        }
    }

    public static final Resource createResource(){
        return (Resource) Proxy.newProxyInstance(ResourceDriver.class.getClassLoader(),
                new Class<?>[] {Resource.class}, new ResourceHandler());
    }
}

Resource://alright, here you can use Nullable model to protect your system from occurred NullPointException …you can see my blog to use Nullable model

/**
 * Created by LY on 2018/11/30.
 */
public interface Resource {
    public void commit();
}

the test code–>

public class test  {

    static ResourcePool pool = new ResourcePool(10);
    //make all thread start together
    static CountDownLatch start = new CountDownLatch(1);
    static CountDownLatch end;

    public static void main(String[] args) throws InterruptedException {
        int threadCount = 100;
        end = new CountDownLatch(threadCount);
        int count = 20;
        AtomicInteger got = new AtomicInteger();
        AtomicInteger nogot = new AtomicInteger();
        for(int i = 0; i < threadCount; i++){
            Thread thread = new Thread(new ResourceRunner(count,got,nogot),"testThread");
            thread.start();
        }
        start.countDown();
        end.await();//wait all thread do task
        System.out.println("total invoke: " + threadCount*count);
        System.out.println("got Resources: " + got);
        System.out.println("no got Resources: " + nogot);
    }


    static class ResourceRunner implements Runnable {
        int count;
        AtomicInteger got;
        AtomicInteger nogot;
        public ResourceRunner(int count, AtomicInteger got, AtomicInteger nogot) {
            this.count = count;
            this.got = got;
            this.nogot = nogot;
        }

        @Override
        public void run() {
            try {
                start.await();
            }catch (Exception e){

            }
            while(count > 0){
                try{
                    Resource resource = pool.fetchResource(1000);
                    if(resource != null){
                        try {
                            resource.commit();
                        }finally {
                            pool.releaseResource(resource);
                            got.incrementAndGet();
                        }
                    }else {
                        nogot.incrementAndGet();
                    }
                }catch (Exception e1){
                }finally {
                    count--;
                }
            }
            end.countDown();
        }

    }
}

we only has 10 Resource instance,

when the thread count is 10,the result is
–total invoke: 200
–got Resources: 200
–no got Resources: 0

when the thread count is 50,the result is
–total invoke: 1000
–got Resources: 816
–no got Resources: 184

when the thread count is 100,the result is
–total invoke: 2000
–got Resources: 1291
–no got Resources: 709

(my mechine is CPU i5-4210M, 4G memory)

中文总结:虽然客户端在这种超时获取的操作下会出现连接无法获取的情况,但是它能够保证客户端线程不会一直挂在连接获取的操作上,而是按时返回,并告知客户端连接获取出现问题,是系统的一种自我保护机制

Version 1.7 ----------- - ADD: Delphi/CBuilder 10.2 Tokyo now supported. - ADD: Delphi/CBuilder 10.1 Berlin now supported. - ADD: Delphi/CBuilder 10 Seattle now supported. - ADD: Delphi/CBuilder XE8 now supported. - ADD: Delphi/CBuilder XE7 now supported. - ADD: Delphi/CBuilder XE6 now supported. - ADD: Delphi/CBuilder XE5 now supported. - ADD: Delphi/CBuilder XE4 now supported. - ADD: Delphi/CBuilder XE3 now supported. - ADD: Delphi/CBuilder XE2 now supported. - ADD: Delphi/CBuilder XE now supported. - ADD: Delphi/CBuilder 2010 now supported. - ADD: Delphi/CBuilder 2009 now supported. - ADD: New demo project FlexCADImport. - FIX: The height of the TFlexRegularPolygon object incorrectly changes with its rotation. - FIX: Added division by zero protect in method TFlexControl.MovePathSegment. - FIX: The background beyond docuemnt wasn't filled when TFlexPanel.DocClipping=True. - FIX: In "Windows ClearType" font rendering mode (OS Windows mode) the "garbage" pixels can appear from the right and from the bottom sides of the painted rectangle of the TFlexText object. - FIX: The result rectangle incorrectly calculated in the TFlexText.GetRefreshRect method. - FIX: Added FPaintCache.rcPaint cleanup in the TFlexPanel.WMPaint method. Now it is possible to define is the drawing take place via WMPaint or via the PaintTo direct call (if rcPaint contain non-empty rectangle then WMPaint in progress). - FIX: The TFlexPanel.FPaintCache field moved in the protected class section. Added rcPaint field in FPaintCache that represents drawing rectangle. - ADD: In the text prcise mode (TFlexText.Precise=True) takes into account the rotation angle (TFlexText.Angle). - FIX: Removed FG_NEWTEXTROTATE directive (the TFlexText Precise mode should be used instead). - FIX: The TFlexRegularPolygon object clones incorrectly drawed in case when TFlexRegularPolygon have alternative brush (gradient, texture). - ADD: Add TFlexPanel.InvalidateControl virtual method which calls from TFle
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值