stackoverflow
stackoverflow

Reputation: 19444

Java Multithreading - How would I spawn two additional threads to increment values within an array?

Scenerio:

  1. I have an integer array of 15 indexes. (each populated with some value)
  2. I want two threads to add two (+2) to the value of the index. Each being aware which index has already been added.
  3. Then join the threads and exit.

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

Answers (4)

Vishal K
Vishal K

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

OldCurmudgeon
OldCurmudgeon

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

hmatar
hmatar

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

Ralf H
Ralf H

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

Related Questions