user2622263
user2622263

Reputation: 59

Java Servlet with Multi-threading

I am trying to create multiple output text data files based on the data present in the servlet request. The constraints to my servlet are that:

The code I have written is such that:

  1. doGet is not synchronized

  2. Within doGet I am creating a new thread pool (reason being that the calling application to my servlet would not send a next request until my servlet returns a response back - so I validate the request and return an instant acknowledgement back to get new requests)

  3. Pass over all request data to the thread created in a new thread pool

  4. Invoke synchronized function to do thread counting and file printing

I am using wait(60000). The problem is that the code produces files with correct threshold (of names) within a minute, but after the timeout of a minute, the files produced (a very few) have capacity exceeded for example, names more than what I have defined in the capacity.

I think it has something to do with the threads who when wake up are causing an issue?

My code is

if(!hashmap_dob.containsKey(key)){
request_count=0;
hashmap_count.put(key, Integer.toString(request_count));

sb1 = new StringBuilder();
sb2 = new StringBuilder();
sb3 = new StringBuilder();

hashmap_dob.put(key, sb1);
hashmap_firstname.put(key, sb2);    
hashmap_surname.put(key, sb3);
                }

if(hashmap_dob.containsKey(key)){
    request_count = Integer.parseInt(hm_count.get(key));
    request_count++;
    hashmap_count.put(key, Integer.toString(request_count));
    hashmap_filehasbeenprinted.put(key, Boolean.toString(fileHasBeenPrinted));  
                }


          hashmap_dob.get(key).append(dateofbirth + "-");
    hashmap_firstname.get(key).append(firstName + "-");
    hashmap_surname.get(key).append(surname + "-");


    if (hashmap_count.get(key).equals(capacity)){

        request_count = 0; 

    dob = hashmap_dob.get(key).toString();
    firstname = hashmap_firstname.get(key).toString();
    surname = hashmap_surname.get(key).toString();

    produceFile(required String parameters for file printing);

    fileHasBeenPrinted = true;
    sb1 = new StringBuilder();
    sb2 = new StringBuilder();
    sb3 = new StringBuilder();

    hashmap_dob.put(key, sb1);
    hashmap_firstname.put(key, sb2);
    hashmap_surname.put(key, sb3);
    hashmap_count.put(key, Integer.toString(request_count));
    hashmap_filehasbeenprinted.put(key, Boolean.toString(fileHasBeenPrinted));
            }
    try{

    wait(Long.parseLong(listenerWaitingTime)); 


        }catch (InterruptedException ie){
            System.out.println("Thread interrupted from wait");
            }

    if(hashmap_filehasbeenprinted.get(key).equals("false")){

    dob = hashmap_dob.get(key).toString();
    firstname = hashmap_firstname.get(key).toString();
    surname = hm_surname.get(key).toString();

    produceFile(required String parameters for file printing );

    sb1 = new StringBuilder();  
    sb2 = new StringBuilder();
    sb3 = new StringBuilder();
    hashmap_dob.put(key, sb1);
    hashmap_firstname.put(key, sb2);
    hashmap_surname.put(key, sb3);
    fileHasBeenPrinted= true;
    request_count =0;
    hashmap_filehasbeenprinted.put(key, Boolean.toString(fileHasBeenPrinted));

    hashmap_count.put(key, Integer.toString(request_count));
            }

If you have got to here, then thank you for reading my question and thanks in advance if you have any thougths on it towards resolution!

Upvotes: 4

Views: 3111

Answers (3)

toto2
toto2

Reputation: 5326

I tried to read your code, but there is a lot of information missing, so if you could please give more details:

1) the indentation is messed up and I'm not sure if there were some mistakes introduced when you copied your code.

2) What is the code you are posting? The code that is called on some other thread after by doGet?

3) Maybe you could also add the variable declarations. Are those thread safe types (ConcurrentHashMap)?

4) I'm not sure we have all the information about fileHasBeenPrinted. Also it seems to be a Boolean, which is not thread safe.

5) you talk about "synchronized" functions, but you did not include those.

EDIT:

If the code you copied is a synchronized method, that means if you have many requests, only one of them only ever runs at a given time. The 60 seconds waiting is always invoked it seems (it is not quite clear with the indentation, but I think there is always a 60 seconds wait, whether the file is written or not). So you lock the synchronized method for 60 seconds before another thread (request) can be processed. That could explain why you are not writing the file after 20 requests, since more than 20 requests can arrive within 60 seconds.

Upvotes: 1

Aaron Digulla
Aaron Digulla

Reputation: 328594

I didn't look at your code but I find your approach pretty complicated. Try this instead:

  1. Create a BlockingQueue for the data to work on.
  2. In the servlet, put the data into a queue and return.
  3. Create a single worker thread at startup which pulls data from the queue with a timeout of 60 seconds and collects them in a list.
  4. If the list has enough elements or when a timeout occurs, write a new file.

Create the thread and the queue in a ServletContextListener. Interrupt the thread to stop it. In the thread, flush the last remaining items to the file when you receive an InterruptedException while waiting on the queue.

Upvotes: 4

Learn More
Learn More

Reputation: 1561

As per my understanding, you want to create/produce a new file in two situations:

  • Number of request hit a predefined threshold.
  • Threshold time-out completes.

I would suggest following:

  1. Use APPLICATION-SCOPED variable: requestMap containing object of HttpServletRequest.
  2. On every servlet hit, just add the received request to map.
  3. Now create listener/filter requestMonitor whatever is suitable, to monitor values of requestMap.
  4. RequestMonitor should check if the requestMap has grown to predefined threshold.
  5. If it has not, then it should allow servlet to add request object.
  6. If it has, then it should print file, empty requestMap, then allow Servlet to add next request.
  7. For timeout, you can check when the last file was produced with LAST_FILE_PRODUCED variable in APPLICATION_SCOPE. This should be updated every time file is produced.

Upvotes: 1

Related Questions