Reputation: 19444
Scenerio:
So far (to where I made it) I'm simply implementing the Runnable interface and supplying the array to computed inside of runnable. I'm stuck with how to do this handshaking from here. Thanks in advance for the help
public class FooRunnable implements Runnable
{
private int[] myArray = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14};
@Override
public void run()
{
for(int i=0; i<myArray.length; i++)
{
myArray[i] = myArray[i] +2;
System.out.println("Thread "+Thread.currentThread().getName()+" Finished index: "+i);
atomicCount.incrementAndGet();
}
}
public static void main(String[] args)
{
FooRunnable r = new FooRunnable();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.setName("Thread One");
t2.setName("Thread Two");
t1.start();
t2.start();
}
}
Results (Goal):
When program exits. the array should have each element of the array incremented by two via two different threads.
Upvotes: 1
Views: 1343
Reputation: 13066
Your code needs to be synchronized
. And this need a proper inter thread communication between the two threads incrementing the value at subsequent index. Although this can be achieved via old ways using wait
and notify
. But now You should switch to java.util.concurrent
package.
The code would look something like this :
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Foo
{
private int[] myArray = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14};//This array can be of any length.
private volatile int lastIndex = 0;
private final Lock lock = new ReentrantLock(true);
private final Condition condition = lock.newCondition();
public void increment()
{
lock.lock();
try
{
if (isDone())
{
return;
}
myArray[lastIndex] = myArray[lastIndex]+2;
System.out.println("Incremented arr["+lastIndex+"] to "+myArray[lastIndex]+" via thread "+Thread.currentThread().getName());
lastIndex++;
condition.signal();
if (!isDone())
{
condition.await();
}
}
catch (Exception ex){}
finally{lock.unlock();}
}
public boolean isDone()
{
return lastIndex == myArray.length;
}
public static void main(String[] args)
{
final Foo foo = new Foo();
Thread th1 = new Thread("Thread1")
{
public void run()
{
while (!foo.isDone())
{
foo.increment();
}
}
};
Thread th2 = new Thread("Thread2")
{
public void run()
{
while (!foo.isDone())
{
foo.increment();
}
}
};
th2.start();th1.start();
}
}
Upvotes: 1
Reputation: 65813
And - of course - there's that other method using Atomics:
public class FooRunnable implements Runnable {
private int[] myArray = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
// Copy myArray into my Atomic version.
private AtomicInteger[] myAtomicArray = new AtomicInteger[myArray.length];
{
for(int i = 0; i < myArray.length; i++ ) {
myAtomicArray[i] = new AtomicInteger(myArray[i]);
}
}
@Override
public void run() {
for (int i = 0; i < myArray.length; i++) {
myAtomicArray[i].addAndGet(2);
}
}
public static void main(String[] args) throws InterruptedException {
FooRunnable r = new FooRunnable();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.setName("Thread One");
t2.setName("Thread Two");
t1.start();
t2.start();
// Wait for them both to finish.
t1.join();
t2.join();
// Print my results.
System.out.println("Results: "+Arrays.toString(r.myAtomicArray));
}
}
which prints
Results: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
Upvotes: 1
Reputation: 2419
You could synchronize the integer accesses by using integer objects. And, whenever a thread wants to increment an integer it should check if that integer has been incremented before by checking if(myArray[i].intVal() == i)
if this returns false then the other thread has incremented this integer. It should be noted that integer value before increment equals index, in this case, i.
public class FooRunnable implements Runnable
{
private Integer[] myArray = {new Integer(0),new Integer(1),new Integer(2),new Integer(3),new Integer(4),new Integer(5),new Integer(6),new Integer(7),new Integer(8),new Integer(9),new Integer(10),new Integer(11),new Integer(12),new Integer(13),new Integer(14)};
@Override
public void run()
{
for(int i=0; i<myArray.length; i++)
{
synchronized(myArray[i]) {
if(myArray[i].intVal() == i) {
myArray[i] = myArray[i] +2;
System.out.println("Thread "+Thread.currentThread().getName()+" Finished index: "+i); }
}
atomicCount.incrementAndGet();
}
}
public static void main(String[] args)
{
FooRunnable r = new FooRunnable();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.setName("Thread One");
t2.setName("Thread Two");
t1.start();
t2.start();
}
}
Upvotes: 1
Reputation: 1474
This will not work. There is the chance that Thread One reads myArray[0] at the same time as Thread Two. Then both threads add 2. You would have to synchronize or use AtomicIntegers in the array. I assume this is some kind of excercise. What do you want to accomplish?
Upvotes: 2