programminglover
programminglover

Reputation: 803

Java how to limit number of threads acting on method

I have java method in my web application doing heavy file operation. The thing is, if more than 5 threads come simultaneously (which will come in testing phase) it breaks down. I mean it cannot handle heavy traffic.

That's why I want to handle maximum 5 requests at a time for method if 6th request come it will wait until one of the first 5 finished

public  synchronized void add(int value){
      File a=new File("D:/heavyFile1");
      File b=new File("D:/heavyFile2");
      File c=new File("D:/heavyFile3");
      //operation on file
  }

I have added synchronized keyword but it only handles one request at a time leading to performance issue as every next thread have to wait till it is finished. Please help me.

Upvotes: 1

Views: 3856

Answers (5)

Mena
Mena

Reputation: 48444

You can use the Executor.newFixedThreadPool idiom, internally to your execution logic.

Full example below:

public class Main {

    public static void main(String[] args) throws Exception {
        Main m = new Main();
        // simulating a window of time where your method is invoked continuously
        for (int i = 0; i < 11; i++) {
            m.doSomething();
        }
        // shutting down executor when done
        m.terminate();
    }

    ExecutorService executor = Executors.newFixedThreadPool(5);

    // internally submits a new task to the executor
    public void doSomething() {
        executor.submit(new Runnable() {
            @Override
            public void run() {
                long wait = ThreadLocalRandom.current().nextLong(2000);
                try {
                    System.out.printf(
                        "%s is sleeping for %dms.%n", 
                        Thread.currentThread().getName(), 
                        wait
                    );
                    Thread.sleep(wait);
                }
                catch (InterruptedException ie) {
                    // suppressed
                }
                System.out.printf(
                    "%s is doing something!%n", 
                    Thread.currentThread().getName()
                );
            }
        });
    }

    public void terminate() throws Exception {
        executor.shutdown();
    }
}

Output

Will vary, in the lines of:

pool-1-thread-1 is sleeping for 1533ms.
pool-1-thread-4 is sleeping for 784ms.
pool-1-thread-3 is sleeping for 684ms.
pool-1-thread-5 is sleeping for 1375ms.
pool-1-thread-2 is sleeping for 1717ms.
pool-1-thread-3 is doing something!
pool-1-thread-3 is sleeping for 1252ms.
pool-1-thread-4 is doing something!
pool-1-thread-4 is sleeping for 301ms.
pool-1-thread-4 is doing something!
pool-1-thread-4 is sleeping for 1140ms.
pool-1-thread-5 is doing something!
pool-1-thread-5 is sleeping for 1454ms.
pool-1-thread-1 is doing something!
pool-1-thread-1 is sleeping for 1594ms.
pool-1-thread-2 is doing something!
pool-1-thread-2 is sleeping for 227ms.
pool-1-thread-3 is doing something!
pool-1-thread-2 is doing something!
pool-1-thread-4 is doing something!
pool-1-thread-5 is doing something!
pool-1-thread-1 is doing something!

Note

See the re-used thread names, those are new submitted tasks that are assigned a vacant thread in the pool.

Upvotes: 3

Martin James
Martin James

Reputation: 24907

Semaphore. Init. with 5 units and have the threads wait at the top of the function and signal at the end.

Upvotes: 1

Stefan
Stefan

Reputation: 12462

Create a thread pool with a fixed size to do that.

Upvotes: 0

Aakash
Aakash

Reputation: 2119

You can use a ThreadPool with a limit of 5 threads. In this, you create a ThreadPool and submit a new thread to it for work on your class. It will only allow maximum number of threads to work simultenously which you have configured. If more threads than configured number comes, they will have to wait until some worker thread finishes it's task.

An example : http://www.javacodegeeks.com/2013/01/java-thread-pool-example-using-executors-and-threadpoolexecutor.html

Upvotes: 0

Adam Arold
Adam Arold

Reputation: 30568

You can create an Executor, and limit the number of tasks it accepts using a Semaphore. Something like this:

private final Semaphore semaphore = new Semaphore(4);
ThreadPoolExecutor tp= new ThreadPoolExecutor(...){
      public void execute(Runnable r){
          semaphore.acquire();
          super.execute(r);
      }    
      public void afterExecute(Runnable r, Thread t){
         semaphore.release();  
         super.afterExecute(r,t);
      }
};

Upvotes: 2

Related Questions