2

I'm writing an application where I need to read blocks in from a single file, each block is roughly 512 bytes. I am also needing to write blocks simultaneously.

One of the ideas I had was BlockReader implements Runnable and BlockWriter implements Runnable and BlockManager manages both the reader and writer.

The problem that I am seeing with most examples that I have found was locking problems and potential deadlock situations. Any ideas how to implement this?

5
  • 2
    Writing non-sequentially will in any case hurt performance. I think a blocking queue solution with a single worker (writing) thread would give better performance and less headaches... Commented Jan 15, 2011 at 19:35
  • @extraneon Seems like that should have been an answer and not a comment ;) Commented Jan 15, 2011 at 19:37
  • Just for clarity - is concurrent writing a requirement or do you just want to data generating threads to dump their data when they are finished so they can get on crunching some different block? Commented Jan 15, 2011 at 19:37
  • WarmWaffles You specify concurrent writing, and my solution does not do concurrent writing :( Commented Jan 15, 2011 at 19:38
  • @extraneon the latter, the loader will obviously load the blocks into memory, the user will mess around with it and then when finished the BlockWriter will commit the block to a file and then drop the block from memory. Commented Jan 15, 2011 at 19:40

2 Answers 2

6

I would recommend the book java Concurrency in Practice, in this case section 5.3 (Producer-consumer pattern).

your solution could look something like:

BlockingQueue<Data> queue = 
    new  LinkedBlockingQueue<Data>(MAX_BLOCKS_IN_QUEUE_UNTIL_BLOCK );

for (int i=0; i < MAX_DATA_PRODUCERS; i++ ) {
   new Thread( new DataProducer( queue ) ).start();
}

new Thread(DataWriter( queue )).start

Obviously DataProducer and DataWriter are runnables.

 class DataProducer implements Runnable {
    ...
    queue.put(data); // blocks if MAX_BLOCKS_IN_QUEUE_UNTIL_BLOCK 
                     // are waiting to be written
                     // This prevents an OutOfMemoryException
    ...
 }

 class DataConsumer implements Runnable {
   ...
   try {
       while(true) {
           writeData(queue.take()); // blocks until there is a block of data
       }
   } catch (InteruptedException e) {
       Thread.currentThread().interrupt();
   }
   ...
 }
Sign up to request clarification or add additional context in comments.

Comments

1

You can have an array of locks e.g. 32 and use the index of the block as a hash to determine which lock to obtain. This way you can have concurrent read/writes (most of the time) and still ensure you won't be read/writing the same block in multiple threads.

2 Comments

I have no doubt that would work but I really think concurrently writing a single file with the seeks that would require is not all that efficient. I think the Producer-Consumer pattern with a single Consumer would be better but I'd love to hear another opinion.
You should achieve the same performance either way. The P-C model may be a better design chose.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.