1

I written a listener which listen to queue continuously, as message arrive it should write that message to file.

@Override
public void handleDelivery(String consumerTag,
                           Envelope envelope,
                           AMQP.BasicProperties properties,
                           byte[] body) throws IOException {
    String response = new String(body);

    String routingKey = envelope.getRoutingKey();
    String contentType = properties.getContentType();
    String correlationId = properties.getCorrelationId();
    System.out.println("response "+ counter+ " :: "+ response);
        try {
            ResponseWriter.responseWrite(response, correlationId);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    Runnable task = new VariableLengthTask(this, envelope.getDeliveryTag(), channel, 1000);
    executorService.submit(task);

}

line in above method

ResponseWriter.responseWrite(response, correlationId);

will call below method:

File file =new File(defaultExcelPath);
        FileOutputStream fop = null;
        PrintWriter writer = null;
        synchronized(file) {
            try {
                List<String> datalist = new ArrayList<String>();
                // add details to datalist....
                // write to the file ..
                .....
                .....
                .....

                fop = new FileOutputStream(defaultExcelPath, true);
                writer = new PrintWriter(fop);
                for(String data : datalist) {
                    writer.println(data);
                }
                writer.close();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                //e.printStackTrace();
                throw e;
            } finally {
                if(fop!= null) fop.close();
                if(writer!= null) writer.close();
            }
      }

but due to handler method listing more than 100 messages in some seconds, file writing method throws below exception

java.io.FileNotFoundException: C:\Files\performanceEvaluator.csv (The process cannot access the file because it is being used by another process)

how I can make the code which write to the file concurrently (or any other way..)

Bharat
  • 407
  • 2
  • 7
  • 16
  • 3
    you are not synchronizing on the same file, each method call create new file object and sets locks on that new object, that's why it's not synchronizing, try synchronizing on `responseWrite` since its a static method just make it synchronized – Eugen Halca Mar 24 '15 at 11:26

2 Answers2

1

Another way would be to just sync when needed on a well known lock your own class. Alternatively you can declare a static variable of type object and lock on that.

class MyClass{

    File file =new File(defaultExcelPath);
    FileOutputStream fop = null;
    PrintWriter writer = null;
   {
        try {//better to move this to its own fn. one fn one thing and probably dont need to sync this
            List<String> datalist = new ArrayList<String>();
            // add details to datalist....
            // write to the file ..
            .....
            .....
            .....
          }catch ...//compelte earlier try

       synchronized(MyClass.class) {
         try{

           // fop = ;
            writer = new PrintWriter(new FileOutputStream(defaultExcelPath, true));
            for(String data : datalist) {
                writer.println(data);
            }
           // writer.close();//dont close here
        } catch (Exception e) {
            //no point throwing error what will the calling code do?
            //jjust log it
            logger.warn(e,e);//if you dont have logging framework get it or make system.out 
        } finally {
             if(writer!= null) try{
           writer.close();
             }catch
            //complete
           // if(fop!= null) writer.close();
           //in this case dont need to open two objects, just wrap it in
           //but if u do have 2 object add seperate try-catch to close each inside the final
        }
    }
  }
   // not tested code please close braces etc
tgkprog
  • 4,493
  • 4
  • 41
  • 70
  • Isn't that a lot more work than adding `synchronized` to a method? – nom Mar 24 '15 at 11:50
  • No, the separate try catch would still be needed eve if its on method. and really the collecting part List datalist = new ArrayList(); // add details to datalist.... // write to the file .. ..... should be on a different method. – tgkprog Mar 24 '15 at 16:49
-1

This is where the keyword synchronized comes into play. Declaring a function in this: public synchronized void function() manner does two things:

  1. First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
  2. Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.

From the Java Tutorials.

user207421
  • 305,947
  • 44
  • 307
  • 483
nom
  • 256
  • 3
  • 16