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)