The result of this program should be the same with 1 or 2 or 3 threads. However, the result with thread 1 is the real one. I think I am meshing up with shared and private variables, what am I doing wrong? Threads have to read from the stack an interval and then calculate the quadrature model.If the error is small enough (i.e. within the specified accuracy) then we have the solution. If the error is still too large, the interval is divided into two with half the required error given to each half of the interval. The quadrature is applied again and so on until the error is small enough. The main problem arises through premature termination of the threads. The stack may be empty, but another thread might be about to place new tasks on it. The solution to this is to keep a count of the "active" threads, that is, the ones which are currently processing an interval. Then the code should terminate only when the stack is empty and there are no active threads...
Please, any help would be very appreciate it?
Cheers
import java.lang.Integer;
class quadtest {
/* Adaptive Quadrature Code. Finds the value of an integral of a
function on a closed interval to a specified accuracy.
*/
public static void main (String args[]) {
int nthreads = Integer.parseInt(args[0]);
double left, right, eps;
double start_time, time;
Quad quad =null;
//Counter counter = new Counter();
left = 0.0;
right = 1.0;
eps = 1.0E-11;
System.out.println("Adaptive Quadrature Program \n");
System.out.println("eps="+eps+" n=10000");
start_time = System.currentTimeMillis();
//Start threads
Thread thread_object [] = new Thread[nthreads];
for(int i=0;i<nthreads;i++){
quad = new Quad(left,right,eps,i,nthreads);
thread_object[i]=new Thread(quad);
}
for(int i=0;i<nthreads;i++){
thread_object[i].start();
}
//Join the threads
for(int i=0;i<nthreads;i++){
try{
thread_object[i].join();
}catch(InterruptedException x){}
}
time = (double) (System.currentTimeMillis()-start_time) / 1000.;
System.out.println("Result = " + quad.getResult() );
System.out.println("Execution time = " + time + " seconds ");
}
}
import java.lang.Runnable;
import java.util.concurrent.atomic.AtomicInteger;
class Quad implements Runnable{
//Shared Variables
static volatile double [][] stack;
static volatile boolean first=false;
static volatile double FinalResult;
static AtomicInteger threadCounter;
static AtomicInteger writing;
static AtomicInteger stackpointer;
static int nthreads;
//Constants
static final int stacksize = 1000;
static final int il = 0;
static final int ir = 1;
static final int ie = 2;
static final int dims = 3;
//Private Variables
private int tid;
double left,right,eps;
private double result;
private double l,r,ep;
public Quad(double left, double right, double eps,int tid,int nthreads) {
this.left = left;
this.right = right;
this.eps = eps;
this.tid=tid;
Quad.nthreads = nthreads;
result = 0.0;
//Only one thread will do it
if(first==false){
first=true;
stack = new double [dims][stacksize];
threadCounter= new AtomicInteger(0);
writing = new AtomicInteger(0);
stackpointer = new AtomicInteger(1);
stack[il][stackpointer.get()] = left;
stack[ir][stackpointer.get()] = right;
stack[ie][stackpointer.get()] = eps;
FinalResult=0.0;
}
}
public void run(){
stackops();
add();
}
public void stackops() {
double abserror,m, est1, est2;
while ((stackpointer.get() >= 1)|| threadCounter.get()>0) {
// Pop next interval off stack.
synchronized (this){
threadCounter.incrementAndGet();
while (writing.get()==1){}
pop();
}
// Compute estimates.
m = 0.5 * (l + r);
est1 = 0.5 * (r - l) * (func(l) + func(r)) ;
est2 = 0.5 * ((m - l) * (func(l) + func(m)) + (r - m) *
(func(m) + func(r)));
abserror = Math.abs(est2-est1) / 3.0;
// Check for desired accuracy: push both halves onto the
// stack if not accurate enough.
if (abserror <= ep) {
result += est2;
//System.out.println("ERROR->ID "+tid+"-abserror="+abserror+"-ep="+ep );
//System.out.flush();
} else {
if (stackpointer.get()+ 2 > stacksize) {
System.out.println("Stack too small, try stacksize = "
+ 2*stacksize);
}
//Push into the stack
synchronized (this){
push(m);
}
}//end else
threadCounter.decrementAndGet();
}//end while
}//end method
private synchronized void add(){
FinalResult +=result;
}
private void pop(){
if(stackpointer.get()>0){
l = stack[il][stackpointer.get()];
r = stack[ir][stackpointer.get()];
ep = stack[ie][stackpointer.get()];
stackpointer.decrementAndGet();
}
}
private void push (double m){
writing.set(1);
if(stackpointer.get()>=-1){
stackpointer.incrementAndGet();
stack[il][stackpointer.get()] = l;
stack[ir][stackpointer.get()] = m;
stack[ie][stackpointer.get()] = ep * 0.5;
stackpointer.incrementAndGet();
stack[il][stackpointer.get()] = m;
stack[ir][stackpointer.get()] = r;
stack[ie][stackpointer.get()] = ep * 0.5;
}
writing.set(0);
}
public double getResult(){
return FinalResult;
}
private double func(double x) {
double q;
int n;
n = 10000;
q = 1000.0;
for(int i=0;i<n;i++) {
q -= x;
}
if (q == 1.0e10) System.out.println("q = " + q);
return x * x;
}
}