CodeMed
CodeMed

Reputation: 9191

making sure one task completes before another starts in java

Can anyone show me a way to force one task in java to complete before the next task is allows to start? Specifically, I want to edit the code below so that the first marked two lines of code are completely finished before the next marked two lines are called.

protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
    throws ServletException, IOException {
      String idString = req.getParameter("id");
      Long id = new Long(idString);
//complete the actions specified on next two lines
      School school = new SchoolDAO().findSchool(id);
      req.setAttribute("school", school);
//before even starting the actions specified on the next two lines
      List<CourseSummary> coursesummaries = new CourseSummaryDAO().findAllcsum(id);
      req.setAttribute("coursesummaries", coursesummaries);

      jsp.forward(req, resp);
}  

EDIT:

To better understand Fernando's suggestion, I am including some relevant parts of SchoolDAO as follows:

public class SchoolDAO extends DataAccessObject{
    public School findSchool(Long id) {
        ResultSet rs = null;
        PreparedStatement statement = null;
        Connection connection = null;
        try {
            connection = getConnection();
            String sql = "select * from schoolprog where id=?";
            statement = connection.prepareStatement(sql);
            statement.setLong(1, id.longValue());
            rs = statement.executeQuery();
            if (!rs.next()) {return null;}
            return readSchool(rs);
         }
         catch (SQLException e) {throw new RuntimeException(e);}
         finally {close(rs, statement, connection);}
      }
      private School readSchool(ResultSet rs) throws SQLException {
          Long id = new Long(rs.getLong("id"));
          String spname = rs.getString("spname");
          String spurl = rs.getString("spurl");
          School school = new School();
          school.setId(id);
          school.setName(spname);
          school.setUrl(spurl);
          return school;
      }
}  

Similarly, CourseSummaryDAO contains:

public class CourseSummaryDAO extends DataAccessObject{
    public List<CourseSummary> findAllcsum(Long sid) {
        LinkedList<CourseSummary> coursesummaries = new LinkedList<CourseSummary>();
        ResultSet rs = null;
        PreparedStatement statement = null;
        Connection connection = null;
        try {
            connection = getConnection(); //this is the line throwing null pointer error
      String sql = "select * from coursetotals where spid=?";
            statement = connection.prepareStatement(sql);
            statement.setLong(1, sid);
            rs = statement.executeQuery();
      //for every row, call read method to extract column 
            //values and place them in a coursesummary instance
            while (rs.next()) {
                CourseSummary coursesummary = readcsum("findAll", rs);
                coursesummaries.add(coursesummary);
            }
            return coursesummaries;
         }
         catch (SQLException e) {throw new RuntimeException(e);} 
         finally {close(rs, statement, connection);}
     }

The line where the program is breaking is:

connection = getConnection(); //

Upvotes: 0

Views: 6245

Answers (3)

Stephen C
Stephen C

Reputation: 718826

If you have two tasks that should be performed serially (i.e. one finishes before the next one starts) then the best answer is to perform them synchronously. For instance, suppose that task1() and task2() are the tasks:

// Wrong way:
Runnable r1 = new Runnable(){
    public void run() {
        task1();
    }};
Runnable r2 = new Runnable(){
    public void run() {
        // Wait for r1 to finish task1 ... somehow
        task2();
    }};

// Right way:
Runnable r = new Runnable(){
    public void run() {
        task1();
        task2();
    }};

And in your case, it looks like the doGet call can only return when it gets the result of both tasks. So that suggests that you shouldn't be using threads at all in this case. Just call task1() and task2() in sequence ... on the request thread.


EDIT

Looking at the doGet method and the two classes that you added subsequently, it looks like the processing is already sequential / serial. That is, the first "task" ends before the second "task" starts.

The problem with getConnection() throwing NullPointerException is (most likely) nothing to do with asynchrony. However I can't be sure of that without seeing the code of getConnection() and the complete stacktrace.

Upvotes: 2

Alex
Alex

Reputation: 71

In Java, everything is normally executed in order, meaning that a given line of code will completely finish executing before the next line will start to do anything. The exception to this rule is when threads come into play. Threads allow multiple blocks of code to execute simultaneously. Because you aren't using any threads in your program (you'd know if you were, don't worry), it's guaranteed that the first two lines of code will complete before the next two begin to be executed.

So, your problem doesn't seem to be that your code is running "out of order". It's likely that your error is somewhere within the getConnection() method if that's what's throwing the NPE.

Upvotes: 1

Fernando
Fernando

Reputation: 7895

Here's an example (see Java Threads waiting value for details)

import java.util.concurrent.CountDownLatch;

class MyTask implements Runnable
{

    CountDownLatch signal;

    public MyTask(CountDownLatch signal)
    {
        this.signal = signal;
    }

    public void run()
    {
        System.out.println("starting task");
        for (int i = 0; i < 10000000; i++)
            Math.random();

        //call when the task is done
        signal.countDown();
    }
}


public class Program
{
    public static void main(String[] args) {
        int workers = 1;
        CountDownLatch signal = new CountDownLatch(workers);

        new Thread(new MyTask(signal)).start();

         try {
                // Waits for all the works to finish ( only 1 in this case)
                signal.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("task is done");
        }

}

This is just a suggestion, maybe there's a better design:

import java.util.concurrent.CountDownLatch;

public class SchoolDAO extends DataAccessObject implements Runnable {

    Long id;
    CountDownLatch signal;
    School searchResult;

    public SchoolDAO(Long id, CountDownLatch signal)
    {
        this.id = id;
        this.signal = signal;
    }

    public void run()
    {
       searchResult = findSchool(id);
       signal.countDown();
    }

    // the other methods didn't change
}  

Now you can call it inside doGet():

CountDownLatch signal = new CountDownLatch(1);
SchoolDAO dao = new SchoolDAO(id, signal);

new Thread(dao).start();
try {        
      signal.await();
    } catch (InterruptedException e) 
    {
      e.printStackTrace();
    }
 School result = dao.searchResult;

Upvotes: 0

Related Questions