Java program wont stop - java

I have an array with the size of n which is filled with the numbers 1..n.
I need to sum this array using m threads by each time taking two elements, sum them up and inserting the sum back to the array.
Here is what I tried to do.
The synchronized part first
public class MultiThreadedSum {
private ArrayBuffer ArrayBufferInst;
private int Sum;
private boolean Flag, StopFlag;
public MultiThreadedSum(ArrayBuffer ArrayBufferInst) {
this.ArrayBufferInst = ArrayBufferInst;
Sum = 0;
Flag = false;
StopFlag = false;
}
public synchronized void Sum2Elements() {
while(Flag){
try {wait();}
catch (InterruptedException e){}
}
Flag = true;
if (StopFlag) {
notifyAll();
return;
}
System.out.println("Removing and adding 2 elements.");
Sum = ArrayBufferInst.Sum2Elements();
notifyAll();
}
public synchronized void InsertElement() {
while(!Flag){
try {wait();}
catch (InterruptedException e){}
}
Flag = false;
if (StopFlag) {
notifyAll();
return;
}
System.out.println("Inserting the sum.");
ArrayBufferInst.InsertElement(Sum);
if (ArrayBufferInst.RetunrSize() == 1) {
StopFlag = true;
}
System.out.println(ArrayBufferInst);
notifyAll();
}
public boolean ReturnStopFlag(){
return StopFlag;
}
#Override
public String toString(){
return ArrayBufferInst.toString();
}
}
I've splitted the m threads to 2 groups, half of them will do the summarization and half will do the adding using wait and notify.
public class Sum2ElementsThread implements Runnable{
private MultiThreadedSum MultiThreadedSumInst;
public Sum2ElementsThread( MultiThreadedSum MultiThreadedSumInst){
this.MultiThreadedSumInst = MultiThreadedSumInst;
}
#Override
public void run() {
while(!MultiThreadedSumInst.ReturnStopFlag())
MultiThreadedSumInst.Sum2Elements();
}
}
public class InsertThread implements Runnable{
private MultiThreadedSum MultiThreadedSumInst;
public InsertThread( MultiThreadedSum MultiThreadedSumInst) {
this.MultiThreadedSumInst = MultiThreadedSumInst;
}
#Override
public void run() {
while(!MultiThreadedSumInst.ReturnStopFlag()) {
MultiThreadedSumInst.InsertElement();
}
}
}
Here is part of the main:
ArrayBufferInst = new ArrayBuffer(n);
System.out.println("The Array");
System.out.println(ArrayBufferInst);
MultiThreadedSumInst = new MultiThreadedSum(ArrayBufferInst);
ExecutorService Threads = Executors.newCachedThreadPool();
for (i = 0; i < m/2; i++)
Threads.execute( new Sum2ElementsThread(MultiThreadedSumInst) );
for (; i < m; i++)
Threads.execute( new InsertThread(MultiThreadedSumInst) );
Threads.shutdown();
while(!MultiThreadedSumInst.ReturnStopFlag()){}
System.out.println("The sum of the array is " + MultiThreadedSumInst);
And the buffer
public class ArrayBuffer {
private ArrayList<Integer> ArrayBufferInst;
public ArrayBuffer(int SizeOfBuffer){
int i;
ArrayBufferInst = new ArrayList<>(SizeOfBuffer);
for (i = 0; i < SizeOfBuffer; i++){
ArrayBufferInst.add(i, i+1);
}
}
public int Sum2Elements(){
if (ArrayBufferInst.size() < 2){
return -1;
}
return ArrayBufferInst.remove(0) + ArrayBufferInst.remove(0);
}
public void InsertElement(int Elem) {
ArrayBufferInst.add(Elem);
}
public int RetunrSize(){
return ArrayBufferInst.size();
}
#Override
public String toString() {
return ArrayBufferInst.toString();
}
}
My question is about the end of the main, sometimes the program stop, sometime it doesn't, I know all the threads are exiting the run method because I checked that.
Sometimes I see the The sum of the array is message, sometimes I don't.

Your problem lies here:
public synchronized void Sum2Elements() {
while(Flag){
try {wait();}
catch (InterruptedException e){}
}
Flag = true;
// rest of method omitted here
}
When this part of the program is executed for the first time Flag is false and the loop is ignored. All subsequent executions of this method will result in a deadlock since this is the only place where you set Flag to false.
Not even interrupting will work, since you have no break in your loop and after the interruption you just go on to the next cycle and wait() forever.
Oh and read this - Java is not c#

It is really a very long code for you task.
Maybe i can propose a different sollution.
You can just split array for m parts (m - is a number of threads) - and each thread would sum it`s own part. When summing is over in each Thread - just sum all part results.
Or maybe i didnt get your task correctly. Specify more details please (the full task).

Related

Multithreaded Prime finder Java

Currently I'm trying to implement a prime finder using threads in java. Unfortunately it does not seem to work the way I intend it to.
What I basically want is that I have a while(true) loop to generate numbers indefinitely. After a number is generated,a thread should grab that number and check if it is a prime number. While the first thread is still checking for prime, the second thread already grabbed the next number to check for prime and so on.
Right now the number generating does work but all threads seem to use the same number, which makes no sense for my implementation.
This is the current state of my project:
public class Main {
public static void main(String[] args) {
int logicalCores = Runtime.getRuntime().availableProcessors();
int startFrom = 0;
startCalc(logicalCores, startFrom);
}
public static void startCalc(int threadCount, int startFrom){
for (int i = 0; i < threadCount; i++ ){
PrimeCalculator calculator = new PrimeCalculator(startFrom, i);
Thread thread = new Thread(calculator);
thread.start();
}
}
}
import static java.lang.Thread.sleep;
public class PrimeCalculator implements Runnable{
int startingCounter;
int id;
public PrimeCalculator(int counter, int id){
this.startingCounter = counter;
this.id = id;
}
#Override
public void run() {
Integer counter = startingCounter;
while(true){
if (isPrime((counter))){
System.out.printf("Thread with ID %d found that %d is a prime! \n", id, counter );
try{
sleep(10000);
} catch (Exception e){
}
}
synchronized (counter){
counter++;
}
}
}
public static boolean isPrime(int n)
{
if (n == 2 || n == 3 || n == 5) return true;
if (n <= 1 || (n&1) == 0) return false;
for (int i = 3; i*i <= n; i += 2)
if (n % i == 0) return false;
return true;
}
}
The problem is that all threads seem to keep checking the same number. E.g the number is 2, but all 16 Threads of my CPU check for prime while in reality a thread like Thread0 should check the number 2 for prime while others are already checking an increment of the counter (e.g Thread15 is already at 16) etc.
EDIT:
I think I need to give a better example of the expected behaviour.
Let's say I have a computer with 4 cores and 4 threads. This would make the logicalCores variable in my main method 4 and create 4 threads in the function "startCalc".
Now a loop should generate numbers from a defined starting point. Let's just say that point is 0.
What should happen now is that a thread, let's just call it thread0 is taking that number and checks if it is a prime. In the meantime the loop generated an increment of the counter and sits at "1" now. Now, because thread0 is still checking if 0 is a prime, a second thread, thread1, grabbed the current counter with the value "1" and is checking if "1" is a prime.
The goal here is that each thread is checking a number for prime in a way which prevents double checking. e.g (we DO NOT want thread0 to check if 1 is a prime because thread1 already did)
Your counter should be a value shared by all threads, so that incrementing it from one thread affects all concurrent threads.
Simplest way to do that is to use a static field. Then use some kind of synchronization to avoid threads incrementing / reading counter concurrently.
public class Main {
public static void main(String[] args) {
int logicalCores = Runtime.getRuntime().availableProcessors();
int startFrom = 0;
startCalc(logicalCores, startFrom);
}
public static void startCalc(int threadCount, int startFrom) {
PrimeCalculator.startAt(startFrom); //Set this for all threads
for (int i = 0; i < threadCount; i++) {
PrimeCalculator calculator = new PrimeCalculator(i);
Thread thread = new Thread(calculator);
thread.start();
}
}
}
import static java.lang.Thread.sleep;
public class PrimeCalculator implements Runnable {
static int counter; //Use static variable
int id;
public static void startAt(int counterStart) { //Set start once for all threads
counter = counterStart;
}
public PrimeCalculator(int id) {
this.id = id;
}
#Override
public void run() {
while (true) {
int current = incrementAndGetCounter();
if (isPrime((current))) {
System.out.printf("Thread with ID %d found that %d is a prime! \n", id, current);
try {
sleep(1000);
} catch (Exception e) {
}
}
}
}
public static boolean isPrime(int n) {
if (n == 2 || n == 3 || n == 5)
return true;
if (n <= 1 || (n & 1) == 0)
return false;
for (int i = 3; i * i <= n; i += 2)
if (n % i == 0)
return false;
return true;
}
//Use synchronized method to increment and get value
//to prevent one thread incrementing it while another one is reading it
private static synchronized int incrementAndGetCounter() {
return counter++;
}
}

counter value is getting rested in multithreading

I tried to print odd number in one thread and even number in another. I tried creating two thread and printing it in run method.
public class OddEven
{
private final int MAX = 10;
private static int counter = 0;
private volatile boolean isOdd = true;
public synchronized void printEven(int counter)
{
try {
if (!isOdd) {
System.out.println(Thread.currentThread().getName() + " " + counter);
counter++;
isOdd = true;
}
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void printOdd(int counter)
{
if (isOdd) {
counter++;
System.out.println(Thread.currentThread().getName() + " " + counter);
isOdd = false;
}
notifyAll();
}
public static void main(String[] args) {
OddEven oddEven = new OddEven();
Thread th1 = new Thread() {
public void run() {
while (OddEven.counter < oddEven.MAX) {
oddEven.printEven(OddEven.counter);
}
}
};
th1.setName("even -");
th1.start();
Thread th2 = new Thread() {
public void run() {
while (OddEven.counter < oddEven.MAX) {
oddEven.printOdd(OddEven.counter);
}
}
};
th2.setName("odd -");
th2.start();
}
}
But it is printing it like below infinitely.
even - 0
odd - 1
even - 0
odd - 1
even - 0
odd - 1
To read: Is Java "pass-by-reference" or "pass-by-value"?
You pass in a primitive. counter++; makes sense only within the method and has no impact on the outer world. count refers to the method param, not to the field this.count.
There is no proper synchronisation placed upon the condition OddEven.counter < oddEven.MAX, so different things may happen.
My advice would be to remove isOdd and do a check on the spot. For instance,
public synchronized void printEven() {
if (counter % 2 != 0) {
System.out.println(Thread.currentThread().getName() + " " + ++counter);
}
}
The line oddEven.printEven(OddEven.counter) passes an integer by value to the printEven method which does not change the value of OddEven.counter when it does counter++ as also pointed in other answers here.
To get the desired output, one option is to remove the passed parameter to both printEven and printOdd methods. And there are many other ways to achieve what you are trying to do here.
And there is also a mistake in the printEven method. counter++; needs to be before the print statement.
This will give you the desired output.

Notify seems to be waking up more than one thread

I am doing a sample program with wait() and notify(), but when notify() is called, more than one thread is wakes up instead of one.
The code is:
public class MyQueue<T> {
Object[] entryArr;
private volatile int addIndex;
private volatile int pending = -1;
private final Object lock = new Object();
private volatile long notifiedThreadId;
private int capacity;
public MyQueue(int capacity) {
entryArr = new Object[capacity];
this.capacity = capacity;
}
public void add(T t) {
synchronized (lock) {
if (pending >= 0) {
try {
pending++;
lock.wait();
System.out.println(notifiedThreadId + ":" + Thread.currentThread().getId());
} catch (InterruptedException e) {
e.printStackTrace();
}
} else if (pending == -1) {
pending++;
}
}
if (addIndex == capacity) { // its ok to replace existing value
addIndex = 0;
}
try {
entryArr[addIndex] = t;
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("ARRAYException:" + Thread.currentThread().getId() + ":" + pending + ":" + addIndex);
e.printStackTrace();
}
addIndex++;
synchronized (lock) {
if (pending > 0) {
pending--;
notifiedThreadId = Thread.currentThread().getId();
lock.notify();
} else if (pending == 0) {
pending--;
}
}
}
}
public class TestMyQueue {
public static void main(String args[]) {
final MyQueue<String> queue = new MyQueue<>(2);
for (int i = 0; i < 200; i++) {
Runnable r = new Runnable() {
#Override
public void run() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
queue.add(Thread.currentThread().getName() + ":" + i);
}
}
};
Thread t = new Thread(r);
t.start();
}
}
}
After some time, I see two threads being wake up by single thread. The output looks like:
91:114
114:124
124:198
198:106
106:202
202:121
121:40
40:42
42:83
83:81
81:17
17:189
189:73
73:66
66:95
95:199
199:68
68:201
201:70
70:110
110:204
204:171
171:87
87:64
64:205
205:115
Here I see 115 thread notified two threads, and 84 thread notified two threads; because of this we are seeing the ArrayIndexOutOfBoundsException.
115:84
115:111
84:203
84:200
ARRAYException:200:199:3
ARRAYException:203:199:3
What is the issue in the program?
What is the issue in the program?
You have a couple of problems with your code that may be causing this behavior. First, as #Holder commented on, there are a lot of code segments that can be run by multiple threads simultaneously that should be protected using synchronized blocks.
For example:
if (addIndex == capacity) {
addIndex = 0;
}
If multiple threads run this then multiple threads might see addIndex == capacity and multiple would be overwriting the 0th index. Another example is:
addIndex++;
This is a classic race condition if 2 threads try to execute this statement at the same time. If addIndex was 0 beforehand, after the 2 threads execute this statement, the value of addIndex might be 1 or 2 depending on the race conditions.
Any statements that could be executed at the same time by multiple threads have to be properly locked within a synchronized block or otherwise protected. Even though you have volatile fields, there can still be race conditions because there are multiple operations being executed.
Also, a classic mistake is to use if statements when checking for over or under flows on your array. They should be while statements to make sure you don't have the class consumer producer race conditions. See my docs here or take a look at the associated SO question: Why does java.util.concurrent.ArrayBlockingQueue use 'while' loops instead of 'if' around calls to await()?

Why my producer thread is not completing its task?

I am working on the producer-consumer problem in Java in which the producer is writing Fibonacci numbers in the pipe and the consumer is consuming it via pipe reader and checking whether it is prime or not.
The problem is that only first 3 Fibonacci primes are generated by the code given below.
What is wrong with it?
package fibonacciprime;
import java.io.*;
import java.lang.*;
public class FibonacciPrime extends Thread {
public static void main(String[] args) throws Exception {
//final PipedOutputStream pout=new PipedOutputStream();
//final PipedInputStream pin=new PipedInputStream();
final PipedWriter pwriter = new PipedWriter();
final PipedReader preader = new PipedReader(pwriter);
//pout.connect(pin);
Thread threadA=new Thread()
{
public void run()
{
for(int i=2;i<1000;i++)
{
synchronized(pwriter)
{
try
{
int temp=5*i*i-4;
int temp1=5*i*i+4;
int p=(int)Math.sqrt(temp1)*(int)Math.sqrt(temp1);
int q=(int)Math.sqrt(temp)*(int)Math.sqrt(temp);
if(p==temp1 || q==temp)
pwriter.write(i);
}catch(Exception e){e.printStackTrace();}
}
}
try {
pwriter.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Thread threadB = new Thread()
{
public void run()
{
int flag=0;
try
{
int temp;
while( ( temp = preader.read() ) != -1)
{
//int k=pin.read();
for(int i=2;i*i < temp;i++)
{
if(temp%i==0)
{
flag=1;
break;
}
}
Thread.sleep(100);
if(flag==0)
System.out.println(temp);
}
preader.close();
}catch(Exception e){e.printStackTrace();}
}
};
threadA.start();
threadB.start();
}
}
Your producer thread is completing its task, but your consumer is buggy, so it doesn't print the appropriate values.
You declare your flag for detecting a prime number outside your while-loop, and never reset its value. Because of this, once the first non-prime number is read (8), all numbers after that will be treated as composite, even when they are prime.
You just need to move the declaration of flag inside your while-loop and your program will work:
while ((temp = preader.read()) != -1) {
int flag = 0; // moved this to inside the loop
for (int i = 2; i * i < temp; i++) {
if (temp % i == 0) {
flag = 1;
break;
}
}
Thread.sleep(100);
if (flag == 0) System.out.println(temp);
}

Summing list with concurrency, filled up by another thread

Have a thread which produces random integers, and puts them into a list. Have also two threads which uses items up from the list concurrently. These threads need to sum up the items which they grab out of the list. Pause these threads until the list is filled. Then print out the summed results of the two threads.
I think, wait() and notify() should be used here. However, I'm not sure I properly understand how this works.
This thread grabs items from the list
#Override
public void run() {
try
{
while (list.size() > 0) {
synchronized (list) {
list.wait();
result += (Integer) list.remove(0);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
This is what fills the list.
#Override
public void run() {
try {
synchronized (list) {
list.wait();
for (int i = 0; i < 10; i++) {
list.add(random.nextInt());
System.out.println("fill");
}
list.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
However, they never finish.
Your code has a number of problem:
You claim to have two threads that read from the list, but you only show one.
You're accessing the list before locking it in the first code block. You need to put the synchronized(list) statement around the while loop.
The code that fills the list waits w/o having anything to notify it.
If your grab-items-from-the-list thread runs first, the list will be empty so it won't do anything. That's probably not what you want.
There is evidence of enough confusion here that I'd suggest trying to think this through in a more abstract way before jumping into writing code.
Well I think I too misunderstood the problem. Here is the correct solution.
This fills the list.
#Override
public void run() {
synchronized(list) {
for (int i = 0; i < 10; i++) {
list.add(random.nextInt());
}
list.notify();
}
}
This sums the items.
#Override
public void run() {
synchronized(list) {
while (list.size() > 0) {
result += (Integer) list.remove(0);
}
list.notify();
}
}
So they just have to lock the list itself, basically.
This, prints out the final solution:
try {
sum1.join();
sum2.join();
System.out.println(sum1.getResult() + sum2.getResult());
} catch (InterruptedException e) {
e.printStackTrace();
}
Anyway, I don't think concurrency implemented like this does not have any practical use - this was just a course task.
The notify() call in the filler thread only notifies one of the waiting threads. Only one thread proceeds to pull one integer. Then it waits again. With nothing firing a notify it waits forever. It needs to only wait if nothing is in the list.
Instead of reinventing the wheel use a BlockingQueue like so:
public Runnable createSum( final BlockingQueue<Integer> queue, final BlockingQueue<Integer> output ) {
return new Runnable() {
public void run() {
Integer result = 0;
while( !queue.isEmpty() ) {
result += queue.take();
}
output.put( result );
}
}
}
public void go() {
BlockingQueue<Integer> input = new ArrayBlockingQueue<Integer>();
BlockingQueue<Integer> output = new ArrayBlockingQueue<Integer>();
Thread runner1 = new Thread( createSum( input, output ) );
Thread runner2 = new Thread( createSum( input, output ) );
for( int i = 0; i < 10; i++ ) {
input.put( random.nextInt() );
}
runner1.start();
runner2.start();
runner1.join();
runner2.join();
Integer result = 0;
while( !output.isEmpty() ) {
result += output.take();
}
System.out.println( result );
}
This solution only starts summing things after the queue is filled but in your solution it was doing the same thing.

Categories