I need help in ArrayList. I have an arraylist of strings. I am looping through this list and sen开发者_Go百科ding them to the output stream one after the other. While I am looping through the list and sending them, it is possible that another thread will be adding some elements to it. After an element is sent, it must be removed from the list as well.
How can I achieve this successfully?
If the items are added to the end of the list, you would better use a Queue instead. There are various thread-safe implementations available in Java5 and above, including ConcurrentLinkedQueue and LinkedBlockingQueue.
In general, the former is the preferable choice, unless you want a bounded blocking queue, in which case use the latter.
Use the right data structure for the job. Use a ConcurrentLinkedQueue
. Here's how it describes itself in its javadoc:
An unbounded thread-safe queue based on linked nodes. This queue orders elements FIFO (first-in-first-out). The head of the queue is that element that has been on the queue the longest time. The tail of the queue is that element that has been on the queue the shortest time. New elements are inserted at the tail of the queue, and the queue retrieval operations obtain elements at the head of the queue. A
ConcurrentLinkedQueue
is an appropriate choice when many threads will share access to a common collection.
I advise to use some implementation of BlockingQueue as ArrayList is not designed for concurrent modifications:
class Producer implements Runnable {
private BlockingQueue<String> queue;
public Producer(BlockingQueue<String> queue) {
this.queue = queue;
}
public void run() {
try {
queue.put("foo");
queue.put("done");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer implements Runnable {
private final BlockingQueue<String> queue;
public Consumer (BlockingQueue<String> queue) {
this.queue = queue;
}
public void run() {
try {
String value = queue.take();
while (!value.equals("done")) {
value = queue.take();
System.out.println(value);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Main {
public static void main(String[] args) throws Exception {
BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
Thread producer = new Thread(new Producer(queue));
Thread consumer = new Thread(new Consumer(queue));
producer.start();
consumer.start();
producer.join();
consumer.join();
}
}
Assuming this is homework, I'll just give some hints.
- both threads can
synchronize
on the list to reserve exclusive access - the
remove()
method returns the object removed - you can remove from the start of the list while adding to the end
This should help you on your way, it always helps if you post what you have so far so we can base out advice on your code.
精彩评论