Reputation: 13
I am trying to do the following:
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!
Upvotes: 1
Views: 1044
Reputation: 6742
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;
}
Upvotes: 1