简体   繁体   中英

Java: synchronized put() with a list of objects

I'm using a LinkedBlockingQueue to handle message objects from other threads. For example, I have something like this:

LinkedBlockingQueue<Message> message_queue = new LinkedBlockingQueue<Message>();

public void run(){
    while(true){
        Message m = message_queue.take();
        handle_message(m);
    }
}

When I add a new message from another thread, I call message_queue.put(m). No problem! My question is this:

How do I synchronize the addition of a SET of messages all at once? Let's say I want to do this:

Message[] messages = {/* some list of message objects */};
for (Message m : messages){
    message_queue.put(m);
}

The problem is that another thread could be doing the same thing, and the messages from one thread are not guaranteed to be queued exactly as I intend. Messages from the competing thread can be "interleaved" inbetween (ie the actual sequence could end up being A, A, B, B, A, B instead of the intended A, A, A, B, B, B) I know I could put the loop in the "put" example into a "synchronized(message_queue){}" block, but would I also need to put that same block around the call to .take()? And obviously, I can't do that, as it would instantly create a deadlock situation, since take() blocks until a new Message is put(), which cannot happen when locked by synchronization. Can I skip the synchronized block on the take() call, having only a synchronized block on the put loop, and get the desired effect? Thanks!

Perhaps the object you want to put onto the queue (and take off) would be a group of messages ?

ie perhaps you have a object representing an ordered collection of messages. Normally it contains just the one message, but could (in this scenario) contain many. That would maintain atomicity and ordering.

Unfortunately you cannot gain access to the individual put and take locks within LinkedBlockingQueue as they are private.

As you mention you could simply wrap the bulk put operation in a synchronized block, which would make this atomic. If you do this I don't understand why you state that you'd also need to add a synchronized block around the take() operation. I don't believe this second synchronized block would be needed (as LinkedBlockingQueue is thread-safe anyway).

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