Link to home
Start Free TrialLog in
Avatar of gagaliya
gagaliya

asked on

how to make this function async?

i have a java function

public String somefunc
{
minifunc();

//i want the function to return a string after minifunc2() to whatever is calling it.  BUT still finish executing 3 4 and 5. Is there an easy way to do that without getting too complicated into threads etc?  
minifunc2();


minifunc3();
minifunc4();
minifunc5();
return "finished";
}

Avatar of cjjclifford
cjjclifford

there is no direct way to return a value in the middle of processing a method.

However, you could pass in a callback object, and use that to pass out information midway:

public class MidwayCallback {
    public void callback( String arg ) {
        // do some processing here
        System.out.println( "Midway!" );
    }
}

public String somefunc( MidwayCallback callback ) {
    minifunc1();
    minifunc2();
    callback.callback( "midway!" );
    minifunc3();
    minifunc4();
    return "finished";
}

however, this will all work in the one thread of execution - to get the code in the callback to operate in parallel with the remainder of the function, you'll have to kick off a seperate thread (simple way is to change the Callback Class, e.g.

public class MidwayCallback {
    public void callback( String arg ) {
        // do some processing in a thread here
        new Thread( new Runnable() {
            public void run() {
                  System.out.println( "Midway: " + arg );
            }
         } );
    }
}
public String somefunc
{
minifunc();

Thread t = new Thread(new Runnable() {
  public void run() {
    minifunc2();
  }
});


minifunc3();
minifunc4();
minifunc5();

t.join(0);
return "finished";
}
Make a Runnable class to execute your async functions:

public class ExecFuncs implements Runnable {
  int func;

  public ExecFuncs( int i ) {
    func = i;
  }

  public void run() {
    if( i == 3 ) {
      minifunc3();
    } else if( i == 4 ) {
       ....             // do 4 and 5 the same way
    }
  }
}


Modify your original call:

public String somefunc
{
minifunc();

minifunc2();


(new Thread( new ExecFuncs( 3 ) ) ).start();
(new Thread( new ExecFuncs( 4 ) ) ).start();
(new Thread( new ExecFuncs( 5 ) ) ).start();
return "finished";
}

Is that simple enough?
public String somefunc
{
minifunc();

minifunc2();
MyThread t=new MyThread();
t.start();

return "finished";
}

class MyThread extends Thread
{
   MyObject o;
    public MyThread(MyObject o)
    {
             this.o=0;
     }
    public void run()
     {

o.minifunc3();
o.minifunc4();
o.minifunc5();
     }
}
hahahaha  all at a time. You are stealing my points ;-)

No Worries. Just Kidding ;-)
forgot to mention

MyObject  is your main class that holds all your functions
I didn't read you question carefully :(( so - disregard my comment
In my model. Just a small change

>>MyThread t=new MyThread();

MyThread t=new MyThread(this);
Avatar of gagaliya

ASKER

hey guys thanks for all the help. I tested the implementation below and it works fine. But i am still worried it will mess up somehow in production, can you guys please take a look at the code below and let me know if this is the corrected way to do this? How about if i call function(String Id) many times in a for loop with different input Id. will that mess up anything? thanks!

public class SomeJavaBean implements java.io.Serializable
{
    String function(String Id)
    {
        MyThread t=new MyThread(Id);
        t.start();
        return "hello world";
    }

    class MyThread extends Thread
    {
         String MyId = null;
         public MyThread(String Id) {  MyId = Id;  }
         public void run()  {  functiontwo(MyId);    }
      }
}
Actually, you could use SwingUtilities.invokeLater(...);
Ummm... wait a sec, before even trying SwingUtilities... are you writing an application or is it a JSP/Applet?
SOLUTION
Avatar of sudhakar_koundinya
sudhakar_koundinya

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
cjjclifford, so you are saying the code below is better?  This is a jsp->javabean->db app and the threading is not used for progress. Mainly the performance is too slow, and we just want to return back to the user(jsp) midway. They dont need to wait until the whole thing finishes.

this is a more accurate version of my code. functiontwo establishes connection to the database, runs a perl script using system(), and calls a bunch other functions.

public class SomeJavaBean implements java.io.Serializable
{
    String function(String Id)
    {
        functionone();
        ............
        MyThread t=new MyThread(Id);
        t.start();
        return "hello world";
    }

    class MyThread extends Thread
    {
         String MyId = null;
         public MyThread(String Id) {  MyId = Id;  }
         public void run()  {  functiontwo(MyId);    }
         public void functiontwo(String id){.....functionthree();functionfour();....}
         public void functionthree(String id){}
         public void functionfour(String id){}

    }
}
something along these lines, yes.
When you say "JavaBean" are you referring to EJB? If you are using a J2EE Container/application server, you should use JMS - the JSP connect to the EJB, which does some work, sends a JMS message to get the remainder of the work done, and then EJB returns to JSP (which in turn returns to user). Then you'd simply have to write a Message-Driven-Bean (MDB) to consume the JMS messages, the MDB would be responsible for all the business logic, and all the threading/scheduling/resource management handled by the application server.

If not EJB, then you should consider using Thread pooling/queuing, to ensure you don't kill the system (thread creation is a little resource intensive, and if you have many many requests all creating threads,  your system will get swamped...)

When you say "perl script run with system()"  do you mean java.lang.Runtime.exec() ? (there is no system() call in Java....) That sounds like the long way around a problem (JSP -> Java -> OS -> Perl -> database) why not rewrite the perl in Java (JSP->Java->Database)
 
cool thanks. this is not ejb, just regular javabean that is called within jsp.  And yes on the perl script, it is runtime.exec() sorry. The script actually calls the mail progie on linux and sends out emails, it doesnt do anything with db. basically my function 1)does some work with db 2)calls a bunch other functions(that connect to db and massages data) 3)calls the per script to send out an email 4)does more work with db.

We use weblogic connection pools. i dont think i need to worry about sync problems right, and will calling the main function ten times(limit) in a for loop like every min be enough to cause resource issues you mentioned? thanks again
large numbers of running threads (hundreds) can cause problems occassionally... if you are using weblogic, you should be able to make use of JMS and a simple message driven bean simply enough... that or a simple ThreadPool might be worth your while (I'm sure there's some good ones to download for free, have a look at Apache commons...)
thanks all