简体   繁体   中英

Java multithreading: why is execution not stopping at join()?

I have a module that deserializes a bunch of resources from files at start. Each takes time so I want to implement this in a multithreaded way so that each thread ingests a single resource. Following some examples I found on the web, I wrote this test class that represents the resource ingestion step of my main module.

public class MultiThreadedResourceIngest {

    private static ResourceClass1 r1 = null;
    private static ResourceClass2 r2 = null;
    private static ResourceClass3 r3 = null;

    static class ResourceReader extends Thread {
        private Thread t = null;
        private int id = -1;
        private String path2read = null;

        ResourceReader( final int id, final String path2read){
           this.id = id;
           this.path2read = path2read;
        }

        public void run() {

           if (path2read != null && path2read.length() > 0)
           {
              switch (id) {
                 case 0:
                    r1 = new ResourceClass1(path2read);
                    break;
                 case 1:
                    r2 = new ResourceClass2(path2read);
                    break;
                 case 2:
                    r3 = new ResourceClass3(path2read);
                    break;
                 default:
                    break;
              }

           }
           log.info(String.format("Thread with id=%d and path=%s exiting", id, path2read));
        }

        public void start ()
        {
           if (t == null)
           {
              t = new Thread (this);
              t.start ();
           }
        }

    }

    public static void main(String[] args) {

        final String[] paths = new String[] {"path1", "path2", "path3"};

        log.info("STARTING MTHREADED READ");
        ArrayList<ResourceReader> rrs = new ArrayList<ResourceReader>();
        for (int i=0; i < paths.length; i++)
        {
           ResourceReader rr = new ResourceReader(i,paths[i]);
           rr.start();
           rrs.add(rr);
        }

        log.info("JOINING");
        for (ResourceReader rr: rrs)
        {
           try {
              rr.join();
           } catch (InterruptedException e) {
              // Thread interrupted
              e.printStackTrace();
           }
        }

        // Want to reach this point only when all resources are ingested
        //
        log.info("MTHREADED FINISHED");
    }

}

So here I have 3 resources and I want to get to the point marked // Want to reach this point... only after all the threads are done. This is why I've implemented the join() loop, except it's not working as intended, ie the log looks like this:

STARTING MTHREADED READ
Thread with id=0 and path=path1 exiting
JOINING
Thread with id=2 and path=path3 exiting
MTHREADED FINISHED
Thread with id=1 and path=path2 exiting

What do I need to change to wait until all resources are read before proceeding?

You declared class ResourceReader extends Thread , but you create another one and launch it inside start:

          t = new Thread (this);
          t.start ();

You should join on this thread, not on

          rr.join();

So just remove your start() method inside ResourceReader and everything will work.

You overrode the start method of thread and it doesn't call super.start(). All this start() does is create a new 2nd thread. Remove that 2nd thread and don't override start().

This way, the call to rr.start() will really start the rr thread, and it will end, and so will the join().

Too complicated! Why not just do this?

static class ResourceReader implements Runnable {
    ...
    public void run() {
       ...
    }
}

public static void main(String[] args) {
    ...
    ArrayList<Thread> rrs = new ArrayList<>();
    for (int i=0; i < paths.length; i++)
    {
       Thread rr = new Thread(new ResourceReader(i,paths[i]));
       rr.start();
       rrs.add(rr);
    }
    ...
    for (Thread rr: rrs)
    {
       try {
          rr.join();
       } catch (InterruptedException e) {
          ...
       }
    }
    ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM