1

The problem is like this. I need to process a large file multiple times. So I think threads will help me increase the time. So far I have done this

The class that implements Runnable :

public class ProcessFile() implements Runnable {
       private int max;
       private int i;
       private int j;

       public ProcessFile(int i, int j) {
             this.i = i;
             this.j = j;
       }
       public void run() {
       //Perform operations on the file
       }
       public int getMaximum() {
             return this.max;
       }
 }

and the class from which I call the thread:

public calss Start {
     public static void main(String[] args) {
        for (int i=0;i<=10;i++) {
             for (int j=0;j<=5;j++) {
                  ProcessFile pf = new ProcessFile(i,j);
                  new Thread(pf).start();
                  int maximum = pf.getMaximum();
                  if (max > currentNr)
                       System.out.println("max is = " + max); 
             }
        }
     }
}

In the code above I intended to compute the maximum each time from the text file, and then return it back in the main program and then process this value. The code above doesn't seem to work since no value is displayed.

EDIT. Since I create the threads in the second loop I want to create 5 threads. Each of them performs the same operations on the file but under different criteria. Also each of this threads should return a value, that should be processed one at a time in the method that created the threads.

GeR
  • 135
  • 1
  • 7
  • http://stackoverflow.com/questions/6916398/communicating-between-two-threads – Sotirios Delimanolis Jun 01 '15 at 19:17
  • `public int getMaximum() { return this.max; }` Did you mean? – Adam Jun 01 '15 at 19:17
  • sorry, i edited the question – GeR Jun 01 '15 at 19:20
  • I don't know much about multithreading but shouldn't you be waiting on the thread to finish with some sort of `.wait()`? – Avantol13 Jun 01 '15 at 19:24
  • There's a `join()` method on `Thread` that will cause the main thread to block until a worker thread completes. But this approach is probably not the right one. Is the file small enough that you can read the whole file into RAM? Do you want to split a single file among several threads to process in parallel? Or are you only trying to have each thread search the entire file for different criteria? – erickson Jun 01 '15 at 19:49
  • I need to search the entire file based on different criteria. – GeR Jun 01 '15 at 19:51
  • Are you writing the code to process the file yourself? It would be more efficient to read the file once, but pass the content to multiple handlers for processing. For example, if the file is line-oriented, callback to each of your processors with each line. Then when the file has been read, query each processor for the optimum. – erickson Jun 01 '15 at 20:23

1 Answers1

3

You have to wait for the thread to complete the job. Here you run a thread and then immediately call pf.getMaximum() in the main thread.

I would suggest using java.util.concurrent.Future to get results of a thread execution, and the Executors framework to create threads.

You can also use Thread.join() on each thread, and then check the results when all your threads have finished.

UPDATE

How about this if you don't want to make any significant changes?

The runnable:

public class ProcessFile implements Runnable {

    private ProcessFileListener listener;
    private int max;
    private int i;
    private int j;

    public ProcessFile(ProcessFileListener listener, int i, int j) {
        this.i = i;
        this.j = j;
        this.listener = listener;
    }

    public void run() {
        //Perform operations on the file
        listener.done(this);
    }

    public int getMaximum() {
        return this.max;
    }
}

The listener:

public interface ProcessFileListener {
    void done(ProcessFile process);
}

The main:

public class Start implements ProcessFileListener {

    private int max = Integer.MIN_VALUE;

    @Override
    public synchronized void done(ProcessFile pf) {

        int maximum = pf.getMaximum();
        if (maximum > max) {
            max = maximum;
            System.out.println("max is = " + max);
        }
    }

    public static void main(String[] args) throws InterruptedException {

        ProcessFileListener listener = new Start();

        for (int i = 0; i <= 10; i++) {
            for (int j = 0; j <= 5; j++) {
                ProcessFile pf = new ProcessFile(listener, i, j);
                new Thread(pf).start();
            }
        }
    }
}

Notice that the method done() is synchronized, i.e. it's thread-safe. That is because you might need to access the same variable (max in this case) from multiple threads.

vempo
  • 3,093
  • 1
  • 14
  • 16
  • Can you help me with an example? From what you said I need to wait for each thread to finish the job. The main purpose why I tried using threads is to speed up the execution time. Maybe my approach is wrong, but if I wait for each thread to finish, I would end up with the same execution time – GeR Jun 01 '15 at 19:34
  • 1
    That's another point. Just having each thread going through the same data doesn't help much. You need to divide the file so that each thread does its part of the job (in parallel with the other threads). Let's say your file has 100 lines. You can run 4 threads: the first one looks for a max number in lines 1-25, the second in 26-50, and so on. Then you wait for all of them to complete and choose the max out of the 4 results. You have to wait for completion in any case, because otherwise you'll get partial results. Does it make sense? – vempo Jun 01 '15 at 19:40
  • yes, it does. but my problem is a little bit more complex. The example posted above is a simplified one. Actually I need to find the best parameters for a gridSearch, and that is why I need to process the file each time. Is there a way of creating lets say 10 threads and each one process the file with different parameters and the return the result one by one? – GeR Jun 01 '15 at 19:45
  • If it's important to print an output as soon as possible, I would do the printing in the job itself, at the end of run(). You can pass an OutputStream to make it more generic (i.e. not to use System.out.println()). Sorry, no better ideas right now. – vempo Jun 01 '15 at 19:56
  • Actually, you can make the main thread wait and be notified by a child thread whenever the child completes, so that the main thread could check its results and do whatever it needs to. But then the main thread has to be waiting (not finished), and woken up to handle each thread's results. – vempo Jun 01 '15 at 20:03
  • This seems a good solution http://stackoverflow.com/questions/702415/how-to-know-if-other-threads-have-finished – vempo Jun 01 '15 at 20:11
  • I've updated the answer with code that I believe does exactly what you need, with minimal changes. – vempo Jun 02 '15 at 18:48