2

I'm writing code using Executor java framework and I'm testing my code on Eclipse, but I saw a strange thing. Using debug mode on eclipse I can print on console an output, or better when I use debug mode step into(F5) I can print an output on console, but if I use debug mode, using step return(F7) or I run the application, it print nothing on console.

Below my output before with debug mode step into(F5):

mapBuffer 
[[B@1af2d44a, [B@18d87d80, [B@618425b5, [B@58695725, [B@543588e6, [B@f5acb9d, [B@4fb3ee4e]

and after with debug mode with step return(F7) or run application:

mapBuffer 
[]

With the same code I have two different output.

public boolean readPieceCount() throws IOException {

        //byte[] buffer = null;
        SortedMap<Integer,byte[]> mapBuffer=new TreeMap<>();    


        ExecutorService executor = Executors.newFixedThreadPool(1);
        executor.submit(() -> {

        for (Integer i=0; i<NUMFILES;i++) 
        {
         Path path = Paths.get(pathPieceCount+"pieceCount"+(i+1)+".csv");
          if(Files.exists(path, LinkOption.NOFOLLOW_LINKS)) 
          {
           byte[] buffer = null;
           try {
            buffer = Files.readAllBytes(path);
                mapBuffer.put(i+1, buffer);
           } catch (IOException e) {
             System.out.println("Exception on readPieceCount!!!");
           }
             }
        }
        });

       System.out.println("mapBuffer ");
       System.out.println(mapBuffer.values());
    executor.shutdown();
/*
more code
*/

this is a part of my code where I have the problem.

I would like to have the same result in all mode. Honestly I spent lots of time yesterday but I'm not understanding where getting wrong. Only a confirmation. When I run this part of code,always I will obtain the same sequence of buffer on the map or executor can change the sequence?

Scripta14
  • 463
  • 2
  • 8
  • 22

2 Answers2

3

You are dealing with concurrency here, so essentially if your main thread hits System.out.println(mapBuffer.values()); line before executor.submit(() -> {} is done with the first mapBuffer.put, you'll print an empty array. Put a wait condition before your print to synchronize your code, using ExecutorService.awaitTermination before printing out the resulting SortedMap.

Check out How to wait for all threads to finish, using ExecutorService? for a good example on how to do it properly.

NotGaeL
  • 8,344
  • 5
  • 40
  • 70
  • 2
    even *worse*, probably the submitted *task* is not yet started when the print is executed – user85421 Nov 08 '19 at 08:31
  • Thanks I've solved my problem. Can I ask you about another piece of code? In this case I should use a code with try\catch condition inside an ExecutorService. Can I add this code to my previous code so as show you the code? – Scripta14 Nov 08 '19 at 13:14
  • Again if your thread raises an exception you can either serve it on the thread itself or use some kind of signaling in your catch block to deal with it in your main thread. A simple flag `executionSuccess` on your task object could do the job, depending on your requirements. Your catch block could then set `this.executionSuccess=false` if you want to deal with that later. – NotGaeL Nov 11 '19 at 07:04
  • 1
    I served the exception on the thread itself. Thanks a lot for your help. – Scripta14 Nov 11 '19 at 11:23
1

Debugging a multithreaded application is not that straight forward like single-threaded application. Your application output in debug mode will fully depend on which place you have put the breakpoints. In debug mode when it hits a debug point the threads which are executing that part of the statement will be suspended and other threads will execute and finish its job. That means your whole application will not wait to resume you suspended threads. As there are multiple threads can be in the suspended thread you have a check that in which sequence you are resuming the threads and also all the threads are resumed or not.

Form your code it is tough to say what is the exact reason for your output without knowing how exactly you are debugging. But it looks like your main/parent thread
is printing mapBuffer values before you resuming/start/finish other executor services thread.

Amit Bera
  • 7,075
  • 1
  • 19
  • 42