Maintain order of Arraylist in multiple threads - java

How can I make sure the print out order same as the order in the original array, when two threads are used? I want it printing '0 1 2 3 4 5 6 7 8 9', but currently the order is not guaranteed. Any way to make it in order? Thank you a lot.
public class Test {
public static void main(String[] args){
DataStore dataStore = new DataStore();
for(int i=0; i<10; i++){
dataStore.add(String.valueOf(i));
}
CopyThread t1 = new CopyThread(dataStore);
CopyThread t2 = new CopyThread(dataStore);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch(Throwable t) {
}
}
}
class CopyThread extends Thread {
private DataStore data;
public CopyThread(DataStore data){
this.data = data;
}
public void run(){
DataStore.Line line = null;
int lineID;
while( (line = data.getLine()) != null ){
lineID = line.id;
System.out.println(Thread.currentThread().getName() + ": " + lineID);
}
}
}
class DataStore {
ArrayList<String> lines = new ArrayList<String>();
int current = 0;
public synchronized Line getLine () {
if (current >= lines.size()) {
return null;
}
Line line = new Line(lines.get(current), current);
current++;
return line;
}
public synchronized void add (String s) {
lines.add(s);
}
public synchronized int size () {
return lines.size();
}
public static class Line {
public String line;
public int id;
public Line (String str, int i) {
line = str;
id = i;
}
}
}

Try Vector instead of ArrayList .
Vector
The Vector class implements a growable array of objects. Like an
array, it contains components that can be accessed using an integer
index. However, the size of a Vector can grow or shrink as needed to
accommodate adding and removing items after the Vector has been
created.
Each vector tries to optimize storage management by maintaining a
capacity and a capacityIncrement. The capacity is always at least as
large as the vector size; it is usually larger because as components
are added to the vector, the vector's storage increases in chunks the
size of capacityIncrement. An application can increase the capacity of
a vector before inserting a large number of components; this reduces
the amount of incremental reallocation.
The Iterators returned by Vector's iterator and listIterator methods
are fail-fast: if the Vector is structurally modified at any time
after the Iterator is created, in any way except through the
Iterator's own remove or add methods, the Iterator will throw a
ConcurrentModificationException. Thus, in the face of concurrent
modification, the Iterator fails quickly and cleanly, rather than
risking arbitrary, non-deterministic behavior at an undetermined time
in the future. The Enumerations returned by Vector's elements method
are not fail-fast.
Note that the fail-fast behavior of an iterator cannot be guaranteed
as it is, generally speaking, impossible to make any hard guarantees
in the presence of unsynchronized concurrent modification. Fail-fast
iterators throw ConcurrentModificationException on a best-effort
basis. Therefore, it would be wrong to write a program that depended
on this exception for its correctness: the fail-fast behavior of
iterators should be used only to detect bugs.

You can use synchronize to achieve that:
synchronized(data) {
while( (line = data.getLine()) != null ){
lineID = line.id;
System.out.println(Thread.currentThread().getName() + ": " + lineID);
}
}

Related

Is it safe clear a Set in a loop if it finds the correct value?

I'm in this situation: if I find a specific value in a HashSet, I have to update a field, clear the set and return the field.
Here one example:
static Set<Integer> testSet = new HashSet<>();
static Integer myField = null; // the field could be already != null
public static int testClearSet()
{
for (int i = 0; i < 100; i++) { // this is just for the test
testSet.add(i);
}
for (Integer n : testSet) {
if (n == 50) {
myField = n;
testSet.clear();
return myField;
}
}
return -1;
}
I'm wondering if doing this to the set it's safe, considering the fact that later on I should reuse the set.
I'm asking this, because I knew that to make changes over a Collection while iterating, is not a "good practice", but this case I think is a little bit different.
A possible solution would be:
boolean clear = false;
for (Integer n : testSet) {
if (n == 50) {
myField = n;
clear = true;
break;
}
}
if (clear) {
testSet.clear();
return myField;
}
So, which one is the right way?
It should be safe to remove elements from a set when using an explicit iterator. Hence the following should be safe:
Iterator<Integer> iterator = testSet.iterator();
while (iterator.hasNext()) {
Integer element = iterator.next();
if (element.intValue() == 50) {
testSet.clear();
break;
}
}
A ConcurrentModificationException is only thrown if you continue iterating after changing it manually.
What you do is change it and abort iterating, so it should be 100% safe (regardless of the for-each implementation).
The real issue is, the readability of the code. A piece of code should ideally do one job, and if this job is complicated, split it up. In particular, your code has two parts, a condition and an action:
if (some condition) do some action
So:
public static int testClearSet() {
if (setConatins(50)) {
myField = 50;
testSet.clear();
return myField;
}
return -1;
}
private static boolean setConatins(int searchFor) {
for (Integer n : testSet) {
if (n == searchFor) {
return true;
}
}
return false;
}
The latter method can be replaced with a single API call, for you to figure out.
If you know that your Set changing only in one thread, so you can clean it like in first example.
Method clear() does not throw ConcurrentModificationException.
Both your code will work.
There is indeed a restriction in modifying the collection when u iterate using fail fast iterators. That means, iterating using fail fast iterator will fail if there is any modification in the collection after the iterator was created. All the default iterators that is returned by java collection classes are fail-fast iterators.
private void removeDataTest (Collection<String> c, String item) {
Iterator<String> iter = c.iterator(); //Iterator is created.
while (iter.hasNext()) {
String data = iter.next();
if (data.equals(item)) {
//c.remove(data); //Problem. Directly modifying collection after this iterator is created. In the next iteration it will throw concurrent modification exception.
iter.remove(); //This is fine. Modify collection through iterator.
//c.clear(); break; //This is also should be okay. Modifying the collection directly, but after that it is breaking out and not using the iterator.
}
}
}
In your code, u don't continue iteration after the set is modified. So should be fine.

Unclear ConcurrentModificationException on separate lists

in a class I've those 2 methods:
public void notifyResult(List<Road> result) {
ArrayList<RoadOverlay> tempRoads = new ArrayList<>();
for(Road road:result){
// Computes and stores the overlays
// ...
tempRoads.add(new RoadOverlay());
}
//switch field when update is done
this.positions = tempRoads;
}
}
private void drawRoadsVO(GL gl) {
// keep a reference on the current instance of the field
// to avoid concurrent modification in notifyResult
ArrayList<RoadOverlay> positionsCopy = this.positions;
int vertexCount = 0;
for (RoadOverlay road : positionsCopy) { //ConcurrentModificationException here
// ...
}
}
Both method run in separate threads. Inside rendering i make no change on the list, and to my understanding i work on separate lists so how could this produce CME?
I'm struggling on this one, and any clue would be welcome. As far as possible I try to avoid penalty of using synchronisation.
regards
Edited a comment in the code
It is usually better to make full copy of a list
ArrayList<RoadOverlay> positionsCopy = new ArrayList<Integer>(this.positions);
As for ConcurrentModificationException, your code looks fine, may be you are modifying current this.positions in some other class methods?
Note that your this.positions variable should be declared as volatile.
Here is next() method of ArrayList iterator
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
ConcurrentModificationException could be thrown only in case then list's elementData is structurally modified
Structural modifications are those that change the size of the list,
or otherwise perturb it in such a fashion that iterations in progress
may yield incorrect results.
the problem is inside drawRoadsVO method your var positionsCopy is not actually a copy, but a reference to the same object this.positions.
In order to make actual copy you should do
ArrayList<RoadOverlay> positionsCopy = new ArrayList(this.positions);

Why Synchronization isn't working in the following Code?

This code sometime throwing an Exception even i have used synchronized Method removeFirst within synchronized block of run method, I am adding and removing element on a synchronizedList.
public class NameDropper extends Thread {
private NameList n1;
public NameDropper(List list) {
this.n1 = new NameList(list);
}
public static void main(String[] args) {
List l = Collections.synchronizedList(new LinkedList());
NameDropper n = new NameDropper(l);
n.n1.add("Ozymandias");
Thread[] t = new NameDropper[10];
for (int i = 1; i <= 10; i++) {
t[i - 1] = new NameDropper(l);
t[i - 1].setName("T" + Integer.toString(i - 1));
t[i - 1].start();
}
}
public void run() {
synchronized (this) {
try {
Thread.sleep(50);
String name = n1.removeFirst();
System.out.println(Thread.currentThread().getName() + ": "
+ name);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class NameList {
private List names = null;
public NameList(List list) {
this.names = list;
}
public synchronized void add(String name) {
names.add(name);
}
public synchronized String removeFirst() {
if (names.size() > 0)
return (String) names.remove(0);
else
return null;
}
}
The exception it is throwing:
T1: Ozymandias
T2: null
*Exception in thread "T3" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.LinkedList.entry(Unknown Source)
at java.util.LinkedList.remove(Unknown Source)
at java.util.Collections$SynchronizedList.remove(Unknown Source)
at NameList.removeFirst(NameDropper.java:57)*
T0: null
T8: null
*at NameDropper.run(NameDropper.java:33)*
T6: null
T4: null
T9: null
T7: null
T5: null
You're creating a new NameDropper instance for each thread.
Therefore, the synchronized methods aren't actually locking, since each instance is never used by two threads.
As pointed out by other people, you have a race condition because all of your threads are synchronized on themselves. You need a common object to synchronize on.
I would recommend that you synchronize on the list itself. It will mean that any instances that are contending for the same list are blocked on each other and any threads that are not, will not be blocked. Your add and remove methods should be:
public void add(String name) {
synchronized (name) {
names.add(name);
}
}
public String removeFirst() {
synchronized (name) {
if (names.size() > 0)
return (String) names.remove(0);
else
return null;
}
}
In general:
1) Since you are creating a new instance of your class each time, you basically have no "common" object for all threads to to lock upon. You should define something like:
static final Object lock = new Object();
and synchronize on this object instead.
2) IMHO it's preferable to implement Runnable rather than extending Thread.
Even though you are using Collections.synchronizedList there is a race condition that exists in your code.
Below is the example of the race codition inside your code.
lock(NameDropper[0]) lock(NameDropper[1])
names.size() > 0 is true names.size() > 0 is true
names.remove(0)
names.remove(0) <--- Error here.
Since you are creating NameDropper instance for each thread which shares single instance of List you have this race condition.
What you can do is create separate list for each NameDropper
List l1 = Collections.synchronizedList(new LinkedList());
t[i - 1] = new NameDropper(l1);
This way each NameDropper will have its own instance of List.
As others have stated, NameList is not being shared. Here is one way with minimal recoding to fix your code (there are others):
Change the constructor to take a NameList (not List).
public NameDropper(NameList list) {
this.n1 = list;
}
Create the NameList where you are currently creating the List.
NameList l = new NameList(Collections.synchronizedList(new LinkedList()));

Solving a ConcurrentModificationException

I am writing a little game which has many circles moving on the screen.
I am managing the circles in two threads as following:
public void run() {
int stepCount = 0;
int dx;
int dy;
while (m_threadTrap){
dx = 0;
dy = 0;
synchronized (m_circles) {
for (Iterator<Circle> it = m_circles.iterator(); it.hasNext();){
Circle c = it.next(); //Exception thrown here.
if (c.getDirX() != 0)
if (stepCount % c.getDirX() == 0){
dx = 1;
}
if (c.getDirY() != 0)
if (stepCount % c.getDirY() == 0){
dy = 1;
}
c.move(dx, dy);
}
}
if (stepCount == 150000){
stepCount = 0;
}
stepCount++;
}
}
m_circles in an ArrayList of Circles.
And the following Thread:
public void run() {
while (m_threadTrap){
int topPosition;
int bottomPosition;
int leftPosition;
int rightPosition;
ArrayList<Circle> removedCircles = new ArrayList<Circle>();
synchronized (m_circles.getCircles()) {
for (Iterator<Circle> it = m_circles.getCircles().iterator(); it.hasNext();){
Circle c = it.next();
// Some calculation to evaluate which circles should be removed
removedCircles.add(c);
}
}
}
try{
Thread.sleep(25);
}
catch (Exception e) { }
m_circles.getCircles().removeAll(removedCircles);
if (m_circles.getCircles().size() < 30)
m_circles.addNewCircle();
repaint();
}
}
My problem is that I get ConcurrentModificationException at the line
Circle c = it.next();
in the first thread. At first I tried going over the ArrayList with a foreach loop and this gave me the same exception.
After researching a bit on this exception I saw two solutions:
1. Putting the part which accesses the collection in a synchronized block.
2. Using the Iterator object of the collection.
Neither of them solved it for me.
For a synchronized() {} block to be effective, all accesses to the protected objects must be wrapped in synchronized blocks. You probably forgot to wrap some access.
Another "gotcha" is that ConcurrentModificationException can also mean that it was concurrently modified in the same thread. For example, if you remove an element from a collection while traversing it, you may get this exception. (As an exception, you can safely remove elements via the iterator itself)
ConcurrentModificationException means that you are iterating over a collection and, while iterating, someone (the current thread or another one) modified the underlying collection without using Iterator.remove(). Whenever you invoke an operation on the Iterator it checks that the underlying collection has not been changed. Using a foreach does not change a thing, since it uses an Iterator to perform the loop.
Your solution are:
create a new collection:
for (Circle c: new ArrayList(m_circles.getCircles()).iterator()) {
// Some calculation to evaluate which circles should be removed
removedCircles.add(c);
}
or synchronize both threads on the same object (you synchronize on different objects, therefore it does not do anything) whenever you are modifying or accessing the collection

Advice for efficient blocking queries

I would like to store tuples objects in a concurent java collection and then have an efficient, blocking query method that returns the first element matching a pattern. If no such element is available, it would block until such element is present.
For instance if I have a class:
public class Pair {
public final String first;
public final String Second;
public Pair( String first, String second ) {
this.first = first;
this.second = second;
}
}
And a collection like:
public class FunkyCollection {
public void add( Pair p ) { /* ... */ }
public Pair get( Pair p ) { /* ... */ }
}
I would like to query it like:
myFunkyCollection.get( new Pair( null, "foo" ) );
which returns the first available pair with the second field equalling "foo" or blocks until such element is added. Another query example:
myFunkyCollection.get( new Pair( null, null ) );
should return the first available pair whatever its values.
Does a solution already exists ? If it is not the case, what do you suggest to implement the get( Pair p ) method ?
Clarification: The method get( Pair p) must also remove the element. The name choice was not very smart. A better name would be take( ... ).
Here's some source code. It basically the same as what cb160 said, but having the source code might help to clear up any questions you may still have. In particular the methods on the FunkyCollection must be synchronized.
As meriton pointed out, the get method performs an O(n) scan for every blocked get every time a new object is added. It also performs an O(n) operation to remove objects. This could be improved by using a data structure similar to a linked list where you can keep an iterator to the last item checked. I haven't provided source code for this optimization, but it shouldn't be too difficult to implement if you need the extra performance.
import java.util.*;
public class BlockingQueries
{
public class Pair
{
public final String first;
public final String second;
public Pair(String first, String second)
{
this.first = first;
this.second = second;
}
}
public class FunkyCollection
{
final ArrayList<Pair> pairs = new ArrayList<Pair>();
public synchronized void add( Pair p )
{
pairs.add(p);
notifyAll();
}
public synchronized Pair get( Pair p ) throws InterruptedException
{
while (true)
{
for (Iterator<Pair> i = pairs.iterator(); i.hasNext(); )
{
Pair pair = i.next();
boolean firstOk = p.first == null || p.first.equals(pair.first);
boolean secondOk = p.second == null || p.second.equals(pair.second);
if (firstOk && secondOk)
{
i.remove();
return pair;
}
}
wait();
}
}
}
class Producer implements Runnable
{
private FunkyCollection funkyCollection;
public Producer(FunkyCollection funkyCollection)
{
this.funkyCollection = funkyCollection;
}
public void run()
{
try
{
for (int i = 0; i < 10; ++i)
{
System.out.println("Adding item " + i);
funkyCollection.add(new Pair("foo" + i, "bar" + i));
Thread.sleep(1000);
}
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
}
}
public void go() throws InterruptedException
{
FunkyCollection funkyCollection = new FunkyCollection();
new Thread(new Producer(funkyCollection)).start();
System.out.println("Fetching bar5.");
funkyCollection.get(new Pair(null, "bar5"));
System.out.println("Fetching foo2.");
funkyCollection.get(new Pair("foo2", null));
System.out.println("Fetching foo8, bar8");
funkyCollection.get(new Pair("foo8", "bar8"));
System.out.println("Finished.");
}
public static void main(String[] args) throws InterruptedException
{
new BlockingQueries().go();
}
}
Output:
Fetching bar5.
Adding item 0
Adding item 1
Adding item 2
Adding item 3
Adding item 4
Adding item 5
Fetching foo2.
Fetching foo8, bar8
Adding item 6
Adding item 7
Adding item 8
Finished.
Adding item 9
Note that I put everything into one source file to make it easier to run.
I know of no existing container that will provide this behavior. One problem you face is the case where no existing entry matches the query. In that case, you'll have to wait for new entries to arrive, and those new entries are supposed to arrive at the tail of the sequence. Given that you're blocking, you don't want to have to examine all the entries that precede the latest addition, because you've already inspected them and determined that they don't match. Hence, you need some way to record your current position, and be able to search forward from there whenever a new entry arrives.
This waiting is a job for a Condition. As suggested in cb160's answer, you should allocate a Condition instance inside your collection, and block on it via Condition#await(). You should also expose a companion overload to your get() method to allow timed waiting:
public Pair get(Pair p) throws InterruptedException;
public Pair get(Pair p, long time, TimeUnit unit) throws InterruptedException;
Upon each call to add(), call on Condition#signalAll() to unblock the threads waiting on unsatisfied get() queries, allowing them to scan the recent additions.
You haven't mentioned how or if items are ever removed from this container. If the container only grows, that simplifies how threads can scan its contents without worrying about contention from other threads mutating the container. Each thread can begin its query with confidence as to the minimum number of entries available to inspect. However, if you allow removal of items, there are many more challenges to confront.
In your FunkyCollection add method you could call notifyAll on the collection itself every time you add an element.
In the get method, if the underlying container (Any suitable conatiner is fine) doesn't contain the value you need, wait on the FunkyCollection. When the wait is notified, check to see if the underlying container contains the result you need. If it does, return the value, otherwise, wait again.
It appears you are looking for an implementation of Tuple Spaces. The Wikipedia article about them lists a few implementations for Java, perhaps you can use one of those. Failing that, you might find an open source implementation to imitate, or relevant research papers.

Categories

Resources