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)

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
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
可能是因为 Python 的 hdf5storage 库和 matio 读取 mat 文件的方式不同导致的。hdf5storage 库保存的 mat 文件也是基于 HDF5 文件格式的,但是不同于 MATLAB 中的 mat 文件,因此可能会导致 matio 无法正确读取。 如果需要在 C++ 中使用 matio 读取 hdf5storage 库保存的 mat 文件,可以考虑使用 HDF5 库来读取。HDF5 库可以读取 hdf5storage 库保存的 mat 文件,因为它们都基于 HDF5 文件格式。 以下是一个使用 HDF5 库读取 mat 文件的示例代码: ```c++ #include <iostream> #include <string> #include <vector> #include "hdf5.h" int main() { // 打开 HDF5 文件 hid_t file_id = H5Fopen("data.mat", H5F_ACC_RDONLY, H5P_DEFAULT); if (file_id < 0) { std::cerr << "Failed to open HDF5 file." << std::endl; return -1; } // 获取MATLAB变量的名称列表 std::vector<std::string> var_names; H5G_info_t group_info; herr_t status = H5Gget_info(file_id, &group_info); if (status >= 0) { var_names.resize(group_info.nlinks); for (unsigned int i = 0; i < group_info.nlinks; i++) { char var_name[1024] = {0}; H5Lget_name_by_idx(file_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, var_name, sizeof(var_name), H5P_DEFAULT); var_names[i] = var_name; } } // 读取变量 for (const auto& var_name : var_names) { hid_t dataset_id = H5Dopen2(file_id, var_name.c_str(), H5P_DEFAULT); if (dataset_id < 0) { std::cerr << "Failed to open dataset: " << var_name << std::endl; continue; } // 获取数据类型 hid_t datatype_id = H5Dget_type(dataset_id); if (datatype_id < 0) { std::cerr << "Failed to get datatype for dataset: " << var_name << std::endl; H5Dclose(dataset_id); continue; } // 获取数据空间 hid_t dataspace_id = H5Dget_space(dataset_id); if (dataspace_id < 0) { std::cerr << "Failed to get dataspace for dataset: " << var_name << std::endl; H5Tclose(datatype_id); H5Dclose(dataset_id); continue; } // 获取数据维度 int ndims = H5Sget_simple_extent_ndims(dataspace_id); if (ndims < 0) { std::cerr << "Failed to get number of dimensions for dataset: " << var_name << std::endl; H5Sclose(dataspace_id); H5Tclose(datatype_id); H5Dclose(dataset_id); continue; } std::vector<hsize_t> dims(ndims); H5Sget_simple_extent_dims(dataspace_id, dims.data(), NULL); // 创建内存空间存储数据 std::vector<double> data(dims[0] * dims[1]); hid_t mem_dataspace_id = H5Screate_simple(2, dims.data(), NULL); // 读取数据 status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, mem_dataspace_id, dataspace_id, H5P_DEFAULT, data.data()); if (status < 0) { std::cerr << "Failed to read dataset: " << var_name << std::endl; } else { std::cout << "Variable: " << var_name << std::endl; for (int i = 0; i < dims[0]; i++) { for (int j = 0; j < dims[1]; j++) { std::cout << data[i * dims[1] + j] << " "; } std::cout << std::endl; } } // 关闭数据集和数据空间 H5Sclose(mem_dataspace_id); H5Sclose(dataspace_id); H5Tclose(datatype_id); H5Dclose(dataset_id); } // 关闭 HDF5 文件 H5Fclose(file_id); return 0; } ``` 注意,在使用 HDF5 库读取 mat 文件时需要先打开 HDF5 文件,然后获取 MATLAB 变量的名称列表,再逐个读取变量。具体的读取操作可以参考上述示例代码。 如果以上方法仍然无法解决问题,可以考虑查看具体的报错信息或者寻求 hdf5storage 和 matio 社区的支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值