david
david

Reputation: 1077

Limit number of active threads for parts of code

I have a multi threaded Java program that mostly works with Apache HTTP Components with proxies. However there is a section in the code that is related to uploading photos which takes up quite a bit of bandwidth and if I don't limit the concurrent threads at that section, I would start to get timeouts. Right now this is what I have, it only allows 1 thread to access the section of the code for uploading photos

public class CommonUtil {
    private static final Object _uploadPhoto = new Object(); 
    public void start(){
        //other code
        synchronized (_uploadPhoto) {
            //all code related to photo upload
        }
        //other code
    }
}

The problem with the code above is that it does not consider the current proxy linked to the thread. I want my program to be able to not allow more than thread to upload photos only if it's the same proxy.

In the program I do have the ability to check which proxy is being currently used by the thread

account.getProxyId()

Let's assume I have three different proxy servers that are being used. In the photoupload section it is ok for threads that have different proxies to use it, but not if they have the same proxy.

Upvotes: 2

Views: 67

Answers (1)

Basil Bourque
Basil Bourque

Reputation: 338201

Executors

Schedule your tasks using the Java Executors framework for concurrency built into later versions of Java. See Tutorial by Oracle.

Thread-pools

Instantiate as many thread-pool-backed executors as you have proxies. Track one executor for each proxy. The tasks for any particular proxy all get assigned to the same executor.

Each executor is backed by its own thread pool with any limit of threads you specify. When more tasks are assigned than can handled at the moment, the executor buffers them up to be assigned when a thread becomes available.

Example code

Ahead of time, establish your executor service objects, one per proxy.

ExecutorService execForProxyA = Executors.newFixedThreadPool​( 3 ) // Three threads maximum at a time working on tasks headed for proxy "A". 
ExecutorService execForProxyB = Executors.newFixedThreadPool​( 2 ) // Two threads maximum at a time working on tasks headed for proxy "B". 
ExecutorService execForProxyC = Executors.newFixedThreadPool​( 5 ) // Five threads maximum at a time working on tasks headed for proxy "C". 

Define a task.

Runnable r = new Runnable() {
    @Override
    public void run() {
        System.out.println( "Hello World!" ) ;
    }
};

Or use the Lambda syntax.

Runnable r = () -> System.out.println( "Hello World!" ) ;

Assign a task to the executor service intended for your desired proxy.

You get back a Future object which you can use to track the task’s progress and completion.

Future future = execForProxyA.submit( r ) ;  // Optionally capture the returned `Future` object.

Important: Be sure to shutdown the executor services appropriately within your app. Otherwise, the backing thread pools may continue running longer than you expect, perhaps even after your app exits.

Upvotes: 1

Related Questions