1

I am trying to do the following: This is what i am trying to do

I want to create an array and use methods executed by a thread. all in one class "embedded class"

A method to randomly find largest number which is 0 and then call it max. A method to find 0 and increment it max + 1.

After that calculate the sum of all array. Check the picture it is more clear.

That's what I've done so far but not working as intended

package javaapplication7;


import java.util.*;
import java.util.concurrent.*;

public class JavaApplication7 {

    private static Array array = new Array();
    public static void main(String[] args) {

        ExecutorService executor = Executors.newCachedThreadPool();
        Scanner input = new Scanner(System.in);

        System.out.println("Enter number");
        int num = input.nextInt();

        int array[] = new int[num];

        for (int i = 0; i < array.length; i++) {
            array[i] = 0;
        }

        for (int i = 0; i < array.length; i++) {
            System.out.println("array["+i+"]: "+array[i]);
        }

        for (int i = 0; i < num; i++) {
            executor.execute(new MyThread());
        }


        executor.shutdown();

        while(!executor.isTerminated()){

        }

        System.out.println("What is balance? ");
    }

    private static class MyThread implements Runnable{
        @Override
        public void run(){
            array.insert();
        }
    }

    private static class Array{
        private int [] array;
        private int maximum;

        public void setArrayNumbers(){
            for (int i = 0; i < array.length; i++) {
                array[i] = 0;
            }
        }
        public int getMax(){
            return maximum;
        }

        public synchronized void insert(){
            try{
                for (int i = 0; i < array.length; i++) {
                    if(array[i] == 0){
                        array[i] = array[i] + 1;
                    }else if(array[i] == 1){
                        array[i] = array[i] + 1;
                    }else if(array[i] == 2){
                        array [i] = array[i] + 1;
                    }
               }
               Thread.sleep(100);
            }
            catch(Exception ex) {
                System.out.println(ex);
            }
        }
    }
}

Help me correcting my mistakes so i can understand multithreading better Thank you!

1 Answer 1

1

First of all, stop to extend Thread. This is actually a very inconvenient way to handle multithreading in Java. There are much better things like the interfaces Runnable and Callable.

I just implemented this the way the exercise is written:

import java.util.Arrays;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Fun implements Runnable {

    int[] numbers;

    public Fun(int[] numbers)
    {
        this.numbers = numbers;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        System.out.print("Please enter the amount of threads: ");
        final int qtyThreads = in.nextInt();

        int[] numbers = new int[qtyThreads];

        for(int i = 0; i<numbers.length; i++)
        {
            numbers[i] = 0;
        }

        ExecutorService exs = Executors.newFixedThreadPool(qtyThreads);

        for(int i = 0; i<qtyThreads; i++)
        {
            exs.submit(new Fun(numbers));
        }

        // already awaits termination
        exs.shutdown();

        int sum = 0;

        for(int number : numbers)
        {
            sum += number;
        }

        System.out.println("ArraySum: "+sum);



    }


    @Override
    public void run() {

        int max = -1;
        for(int i = 0; i<numbers.length; i++)
        {
            if(numbers[i] > max)
            {
                max = numbers[i];
            }
        }

        for(int i = 0; i<numbers.length; i++)
        {
            if(numbers[i] == 0)
            {
                numbers[i] = ++max;
                break;
            }
        }

    }

}

And here the part about thread-safety:

To implement this in this case, you'd have to lock the array each time you do the writing, so no thread get's concurrent modifications.

So in the run method we'd have a this.lock.lock(); before the second loop and a this.lock.unlock(); after the second loop.

The lock has the Type ReentrantLock and is passed to the constructor of Fun, so every Thread has the same lock instance.

The lock() method actually waits until the lock is available. If you do something wrong here and don't unlock the lock, you'll cause a deadlock situation.

Basically, when it comes to validate the sum, the value of the sum should always be sum(n) = sum(n-1)+n - you can find this out by either doing some maths stuff, or as I was never particular good in maths, I just did the following:

1: 1
2: 3 (+2)
3: 6 (+5)
4: 10 (+9)
5: 15 (+14)

Which then lead to the conclusion that the sum is always the previous sum plus the user input. This however is not how you do a mathematical proof.

If you want to check if your multithreaded solution is working properly, you can always write a singlethreaded one and compare these values - this is a lot easier than doing it on paper, which you wouldn't do for high numbers anyway:

public static int validateWithSingleThread(int n)
{

    int[] numbers = new int[n];

    for(int itt = 0; itt<n; itt++)
    {
        int max = -1;
        for(int i = 0; i<numbers.length; i++)
        {
            if(numbers[i] > max)
            {
                max = numbers[i];
            }
        }

        for(int i = 0; i<numbers.length; i++)
        {
            if(numbers[i] == 0)
            {
                numbers[i] = ++max;
            }
        }       
    }

    int sum = 0;

    for(int number : numbers)
    {
        sum += number;
    }


    return sum;

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

6 Comments

Why are numbers being set to 0? Won't they automatically be initialized with 0?
Because I literally followed the instructions given - and sometimes universities and schools tick in a weird way, but you're obviously right.
Each time I run your multi-threaded code, with the same number of threads (9), I get a different sum each time. Why is that?
That has something to do with the concurrent modification of the array, caching and a dozen things about the JVM, I've all forgotten about since I had the module for parallel programming in university years ago and didn't need the exact knowledge after that. With proper locking, you should get the same result every time.
@maio290 "A dozen things about the JVM" - Can't blame it on the JVM. Even with C# or other concurrent languages, you'll need to account for happened-before relationships, which your code currently doesn't do.
|

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.