1

I have a code which has following methods:

  • downloadFile() - download file from ftpserver

  • processFile() - read file line by line and process the line

  • sendSMS() - send SMS to vendors how many records got processed.

The processFile method reads each line,builds a URL string and hits URL.To make the process faster I have used thread concept.

//snippet in processFile method
while ((sCurrentLine = br.readLine()) != null) {
    String[] arr = sCurrentLine.split("\t");

    if (//some condition) {
        String url = //build url from the current line  
        Thread t = new Thread(new MyClass(url));
        t.start();
    } 
}

public MyClass(String strUrl) {
    this.strUrl = strUrl;
}

public void run() {
    urlHit(strUrl);//call function to hit current URL
}

Now my concern is sendSMS method should get called only after all URLs got hit.

I tried using join method which works fine but it is as good as not using threads.

tom redfern
  • 30,562
  • 14
  • 91
  • 126
  • Using `async` is easier for multitreaded code. – Niyoko Oct 28 '16 at 05:09
  • So you can use `await Task.WhenAll` – Niyoko Oct 28 '16 at 05:10
  • You have a problem with calling `join()`, yet you do not show how you call it. Please rectify this. –  Nov 01 '16 at 19:22
  • @arkadiy refer above code:Thread t = new Thread(new MyClass(url)); t.start();t.join(); – DontDiscloseMe Nov 03 '16 at 05:18
  • The code in the question shows `start()` but not `join()`. Please edit. More substantially, `start()` followed by `join()` before another `start()` causes all threads to run sequentially. No parallelization happens.. –  Nov 03 '16 at 11:42
  • Please read full question @Arkadiy ,I wrote the same reason why I am avoiding join method.Same is the reason for not keeping join method in my question code – DontDiscloseMe Nov 07 '16 at 06:39
  • Your problem comes from the way you use join method. –  Nov 07 '16 at 10:45

3 Answers3

0

You need to apply synchronisation, and there are various ways of applying synchronisation in java. You can use wait() and notify() where the sendSms waits until a notification is recieved that the urls have been hit. Check the examples here to help you out.

Ramsha Khan
  • 99
  • 1
  • 8
0

Use ExecutorService and invokeAll API.

Refer to this post on usage of invokeALl()

How to use invokeAll() to let all thread pool do their task?

Replace your

Thread t = new Thread(new MyClass(url));

with

Callable task and submit your Callable tasks to ExecutorService.

Once you are done with processing of all URLs by following of one of available options, invoke sendSMS() method.

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
0

Using an executor in this case is a good idea to limit the number of threads being executed concurrently. Your steps to achieve what you are after are as follows:

  • Construct a list of Callable, each would create the URL and hit the constructed URL.
  • Create a Thread pool executor and call invokeAll with list of Callable objects as parameter.
  • Once invokeAll returns, you can loop on the returned list of Callable and call get() to get your result if needed, for instance to confirm that the URL was hit successfully.

For instance, the following would look like the code you use to create the Callable list:

List<Callable> createUrlAndHit = new ArrayList<Callable>();
while ((sCurrentLine = br.readLine()) != null) {
    String[] arr = sCurrentLine.split("\t");

    if (//some condition) {
        createUrlAndHit.add(new Callable(){
           //Add your logic here...., or create a specific implementation of callable to instantiate with your url
        });
    } 
}

The next step would be to invokeAll:

ExecutorService executor = Executors.newFixedThreadPool(...);
List<Future<Callable>> futures = executor.invokeAll(createUrlAndHit);
//Loop on results and send SMS
for(Callable c : futures){
  //send sms..
}
OKAN
  • 421
  • 1
  • 5
  • 10