1

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.

5
  • You might want to consider partitioning your array into two segments ([0, 7] and [8, 14]), and giving each Thread its own partition to increment. Commented Mar 2, 2013 at 21:53
  • 1
    I don't exactly get the expected behavior (what the program should do), and how your current solution does not satisfy the requirements. Commented Mar 2, 2013 at 21:54
  • @gd1 Revised question. Please see below the code snippet. Commented Mar 2, 2013 at 21:56
  • OK then Jeffrey's comment and Ralf's answer are both correct and useful. Commented Mar 2, 2013 at 21:57
  • @gd1 I dont wish to partition the array off. Is that possible with that being said? Commented Mar 2, 2013 at 21:59

4 Answers 4

2

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?

Sign up to request clarification or add additional context in comments.

1 Comment

I'm aware this will not work. I'm hoping someone can show me a code demonstration of how this exercise would be done (given the scenario)
1

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();
    }
}

5 Comments

You mean why Foo object made final.right?? It is done so that the object foo could be accessed within the run method of anonymous inner class defined for Thread
For your previous response. Yeah I apologize, I was being a bit slow there. Anyhow, How much more difficult would this be by implementing the Runnable interface as opposed to overriding run() with inner classes? Drawbacks?
That wont be difficult..It all depends upon the programmer's choice and taste ..You can do the same using Thread th = new Thread( new Runnable() {public void run() { while(!foo.isDone()){foo.increment()}}}); And there is no performance difference between the above two methods ..
@Mrshll187: One thing that i missed in the previous post is to declare lastIndex as volatile. It should be volatile because it is shared between two threads so both threads should have latest value of lastIndex available to them. My apologies for that..
Thank you. Your responses have been most helpful.
1

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();
    }
}

3 Comments

Awesome. Thanks for the response. What is the if(myArray[i] == i) exactly doing?
@Mrshll187 explanation for that is on my solution above.
Are your stuck using the wrapper classes with synchronization blocks?
1

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]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.