Solved

how to make this function async?

Posted on 2004-11-01
384 Views
Last Modified: 2008-03-04
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";
}

0
Question by:gagaliya
    18 Comments
     
    LVL 11

    Expert Comment

    by: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 );
                }
             } );
        }
    }
    0
     
    LVL 9

    Expert Comment

    by:Venci75
    public String somefunc
    {
    minifunc();

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


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

    t.join(0);
    return "finished";
    }
    0
     
    LVL 5

    Expert Comment

    by:TrekkyLeaper
    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?
    0
     
    LVL 14

    Expert Comment

    by:sudhakar_koundinya
    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();
         }
    }
    0
     
    LVL 14

    Expert Comment

    by:sudhakar_koundinya
    hahahaha  all at a time. You are stealing my points ;-)

    No Worries. Just Kidding ;-)
    0
     
    LVL 14

    Expert Comment

    by:sudhakar_koundinya
    forgot to mention

    MyObject  is your main class that holds all your functions
    0
     
    LVL 9

    Expert Comment

    by:Venci75
    I didn't read you question carefully :(( so - disregard my comment
    0
     
    LVL 14

    Expert Comment

    by:sudhakar_koundinya
    In my model. Just a small change

    >>MyThread t=new MyThread();

    MyThread t=new MyThread(this);
    0
     
    LVL 1

    Author Comment

    by:gagaliya
    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);    }
          }
    }
    0
     
    LVL 9

    Expert Comment

    by:doronb
    Actually, you could use SwingUtilities.invokeLater(...);
    0
     
    LVL 9

    Expert Comment

    by:doronb
    Ummm... wait a sec, before even trying SwingUtilities... are you writing an application or is it a JSP/Applet?
    0
     
    LVL 14

    Assisted Solution

    by:sudhakar_koundinya
    Try this model. But I think it will a bit slow.

    Hmmmmm..., First try it and let me know. I will help you furtherif you face any problems

    public class SomeJavaBean implements java.io.Serializable
    {
        String function(String Id)
        {
                 synchronized(this)
              {
            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()  {  synchronized(this){functiontwo(MyId);  }  }
          }
    }
    0
     
    LVL 11

    Accepted Solution

    by:
    gagaliya, you didn't post what functiontwo() does, so we can't really say what effects this would have.
    Your initial request was to "return" a string in the middle of processing, before continuing on, I assumed you wanted to somehow return progress information, or something along this line - if you just want to have something process in the background, then you would be better to implement "functiontwo()" as a member function of the MyThread class (or even putting the logic into the run() method), keep all the code together and keep clean boundaries between classes (loose coupling, high cohesion). Then whenever you want the functionality run, just create a new MyThread class and start it!

    sudhakar - Synchronizing the way you have won't do anything really - the code in SomeJavaBean.function() only deals with method-local variables, so synchronization will only result in queuing up requests to this function. Synchronization in MyThread.run() does nothing, since each call to SomeJavaBean.function() will create a new MyThread object, which is what is being synchronized in your code (i.e. each synchronization block has a different object to synchronize on: no synchronization...)
    0
     
    LVL 1

    Author Comment

    by:gagaliya
    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){}

        }
    }
    0
     
    LVL 11

    Expert Comment

    by:cjjclifford
    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)
     
    0
     
    LVL 1

    Author Comment

    by:gagaliya
    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
    0
     
    LVL 11

    Expert Comment

    by:cjjclifford
    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...)
    0
     
    LVL 1

    Author Comment

    by:gagaliya
    thanks all
    0

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    Cisco Complete Network Certification Training

    If you’re an IT engineer or technician, it's time you take your career to the next level. This elite training bundle is brimming with all of the information you need to learn to sit for Cisco CNNA, CCNP, and CCENT certification exams.

    Suggested Solutions

    INTRODUCTION Working with files is a moderately common task in Java.  For most projects hard coding the file names, using parameters in configuration files, or using command-line arguments is sufficient.   However, when your application has vi…
    Java had always been an easily readable and understandable language.  Some relatively recent changes in the language seem to be changing this pretty fast, and anyone that had not seen any Java code for the last 5 years will possibly have issues unde…
    Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
    This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.

    934 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    18 Experts available now in Live!

    Get 1:1 Help Now