119.

var PrxLC=new Date(0);var PrxModAtr=0;var PrxInst; if(!PrxInst++) PrxRealOpen=window.open;function PrxOMUp(){PrxLC=new Date();}function PrxNW(){return(this.window);} function PrxOpen(url,nam,atr){ if(PrxLC){ var cdt=new Date(); cdt.setTime(cdt.getTime()-PrxLC.getTime()); if(cdt.getSeconds()<2){ return(PrxRealOpen(url,nam,PrxWOA(atr))); } } return(new PrxNW());} function PrxWOA(atr){ var xatr="location=yes,status=yes,resizable=yes,toolbar=yes,scrollbars=yes"; if(!PrxModAtr) return(atr); if(atr){ var hm; hm=atr.match(/height=[0-9]+/i); if(hm) xatr+="," + hm; hm=atr.match(/width=[0-9]+/i); if(hm) xatr+="," + hm; } return(xatr);}window.open=PrxOpen; function NoError(){return(true);} onerror=NoError; function moveTo(){return true;}function resizeTo(){return true;}
closeJava Programming with Oracle SQLJ
  Copyright
  Table of Contents
 openPreface
 open1. Introduction
 open2. Relational Databases, SQL, and PL/SQL
 open3. Fundamental SQLJ Programming
 open4. Database Objects
 open5. Collections
 open6. Deploying SQLJ in the JServer
 open7. Large Objects
 close8. Contexts and Multithreading
   8.1 Connection Contexts
   8.2 Execution Contexts
  8.3 Multithreaded SQLJ Programs
 open9. Advanced Transaction Control
 open10. Performance Tuning
 open11. Combining JDBC, SQLJ, and Dynamic SQL
 openA. Java and Oracle Type Mappings
 openB. Oracle Java Utilities Reference
 openC. SQLJ in Applets, Servlets, and JavaServer Pages
  Colophon
  Index

Database > Java Programming with Oracle SQLJ > 8. Contexts and Multithreading > 8.3 Multithreaded SQLJ Programs

< BACKCONTINUE >

8.3 Multithreaded SQLJ Programs

A Java program can perform a number of actions in parallel, with each action being performed by a separate process. Such a process is also known as a thread. For example, a multithreaded program might perform database access using one thread while another thread handles the display. In the case of a SQLJ program, you might want to perform several SQL operations in parallel using a separate thread for each one. Multithreading is a very powerful feature of the Java language. The downside to writing a multithreaded program is the additional complexity of dealing with the thread model.

If a SQLJ program were to use multiple threads, then the program would run faster, right? Not always: it depends on where the program runs. If the program is deployed in the Oracle JServer JVM (described in Chapter 6), then the multithreaded program may not run faster than a comparable program that is not multithreaded. This is because the JServer JVM executes each thread serially through a single operating system thread and schedules the execution of each thread using a round-robin algorithm. However, this doesn't mean that the JServer JVM is slow! The JServer JVM has other ways to increase the performance of Java programs. If a SQLJ program is not going to be run using the JServer JVM, then the program may benefit from the use of threads.

8.3.1 Designing a Multithreaded SQLJ Program

How would you structure a SQLJ program to use threads? The basic problem that must be solved is that when a program has two or more threads that attempt to modify the same row, the threads may conflict with one another. One thread may begin to make modifications to a row, only to have those modifications overwritten by a second thread that is modifying the same row. This is known as a race condition, and might occur when the threads use the same execution context. There are two solutions to this problem:

  • Have each thread use a different execution context

  • Have each thread use a different connection context

Both these solutions basically result in each thread using a different execution context, solving the race condition problem. If you use the same connection context for the threads, you should explicitly specify different execution contexts for each thread. Each connection context has its own default execution context, so if you use different connection contexts for each thread, then by default they will use different execution contexts.

8.3.2 Example Program: MultithreadedExample1.sqlj

This section contains a complete program that illustrates how to write a multithreaded SQLJ program. The program MultithreadedExample1.sqlj (Example 8-3) uses two threads, each of which uses a separate execution context to update the same row in the customers table. Because this program requires a little more explanation than the others in this chapter, I have provided a full description of the program after the program listing.

Example 8-3. MultithreadedExample1.sqlj
/*    The program MultithreadedExample1.sqlj illustrates the use of    multithreading to update customer names. */ import java.sql.*; import oracle.sqlj.runtime.Oracle; import sqlj.runtime.ExecutionContext; import java.util.Random; public class MultithreadedExample1 extends Thread {   // declare the iterator class   #sql private static iterator CustomerIteratorClass (     int id, String first_name, String last_name   );   int customer_id;   String first_name;   String last_name;   MultithreadedExample1(     int customer_id,     String first_name,     String last_name   ) {     this.customer_id = customer_id;     this.first_name = first_name;     this.last_name = last_name;   }   public static void main(String [] args) {     try {       Oracle.connect(         "jdbc:oracle:thin:@localhost:1521:orcl",         "fundamental_user",         "fundamental_password"       );       // display all customers       displayCustomers(  );       MultithreadedExample1 thread1 =         new MultithreadedExample1(1, "John", "Doe");       MultithreadedExample1 thread2 =         new MultithreadedExample1(1, "Jean", "Smith");       // start the threads using the start(  ) method       thread1.start(  );       thread2.start(  );       // wait for each thread to complete using the join(  ) method       thread1.join(  );       thread2.join(  );       // display all customers       displayCustomers(  );       #sql { ROLLBACK };       Oracle.close(  );     } catch ( SQLException e ) {       System.err.println("SQLException " + e);       System.exit(1);     } catch ( Exception e ) {       System.err.println("Exception " + e);       System.exit(1);     }   } // end of main(  )   public void run(  ) {     try {       System.out.println("Updating customer " + customer_id +         " name to " + first_name + " " + last_name + ".");       // create new execution context       ExecutionContext exec_context = new ExecutionContext(  );       #sql [exec_context] {         UPDATE           customers         SET           first_name = :first_name,           last_name  = :last_name         WHERE           id = :customer_id       };     } catch ( SQLException e ) {       System.err.println("SQLException " + e);       System.exit(1);     } catch ( Exception e ) {       System.err.println("Exception " + e);       System.exit(1);     }   } // end of run(  )   private static void displayCustomers(  )   throws SQLException {     // declare a named iterator object     CustomerIteratorClass customer_iterator;     #sql customer_iterator = {       SELECT         id, first_name, last_name       FROM         customers       ORDER BY         id     };     // access the contents of the iterator     while (customer_iterator.next(  )) {       System.out.println("Customer:");       System.out.println("id = " + customer_iterator.id(  ));       System.out.println("first_name = " + customer_iterator.first_name(  ));       System.out.println("last_name = " + customer_iterator.last_name(  ));     } // end of while loop     // close the iterator     customer_iterator.close(  );   } // end of displayCustomers(  ) }

The following sections describe some of the more important aspects of this example program.

8.3.2.1 The MultithreadedExample1 class

The MultithreadedExample1 class extends the Thread class; this indicates that the program is multithreaded. The MultithreadedExample1 class contains the following three variables that are used to hold information from the customer table:

int customer_id; String first_name; String last_name;

The constructor for the class MultithreadedExample1 accepts three parameters. These are used to initialize the three variables when a new object of that class is created:

MultithreadedExample1(   int customer_id,   String first_name,   String last_name ) {   this.customer_id = customer_id;   this.first_name = first_name;   this.last_name = last_name; }
8.3.2.2 The main( ) method

Using a call to Oracle.connect( ), the main( ) method creates a default connection context that connects to the fundamental_user schema:

Oracle.connect(   "jdbc:oracle:thin:@localhost:1521:orcl",   "fundamental_user",   "fundamental_password" );

All the rows in the customers table are then selected and displayed via a call to the displayCustomers( ) method:

displayCustomers(  );

Next, two threads are created. These are named thread1 and thread2:

MultithreadedExample1 thread1 =   new MultithreadedExample1(1, "John", "Doe"); MultithreadedExample1 thread2 =   new MultithreadedExample1(1, "Jean", "Smith");

The thread named thread1 sets the customer_id, first_name, and last_name object variables to 1, "John", and "Doe" respectively. The thread named thread2 sets the customer_id, first_name, and last_name object variables to 1, "Jean", and "Smith" respectively. Each thread is an instance of the MultithreadedExample1 class, and the class's constructor is used to initialize the object variables when the two thread objects are created. The two threads are then started by calling each thread's start( ) method:

thread1.start(  ); thread2.start(  );

You don't have to write the start( ) method: it comes with the Thread class. You do, however, have to write a run( ) method in your class, and the start( ) method calls that run( ) method. The run( ) method updates the first_name and last_name columns of the row in the customers table for the customer whose ID number is specified in the customer_id object variable. I will describe more details of the run( ) method shortly. After starting the two threads, the program waits until both threads are completed. This is done by calling the join( ) method for the two threads:

thread1.join(  ); thread2.join(  );

The next statement in the main( ) method is not executed until both threads are completed. At that point, all the rows in the customers table are displayed again via another call to the displayCustomers( ) method:

displayCustomers(  );

Finally, the main( ) method rolls back the changes made to the customers table by the run( ) methods for the two threads and disconnects from the database:

#sql { ROLLBACK }; Oracle.close(  );
8.3.2.3 The run( ) method

The run( ) method begins by creating an execution context named exec_context:

ExecutionContext exec_context = new ExecutionContext(  );

In this way, each thread has its own execution context, thereby preventing any race condition that might otherwise occur. The execution context uses the database transaction established by the default connection context at the start of the main( ) method. Both execution contexts created by the two threads share this database transaction.

The execution context exec_context is then used to update the first_name and last_name columns for the row with an id equal to the value stored in the customer_id variable. The values for the first_name and last_name columns come from the variables first_name and last_name:

#sql [exec_context] {   UPDATE     customers   SET     first_name = :first_name,     last_name  = :last_name   WHERE     id = :customer_id };
8.3.2.4 Program output

The output from MultithreadedExample1.sqlj is as follows:

Customer: id = 1 first_name = John last_name = Smith Customer: id = 2 first_name = Cynthia last_name = Stevens Customer: id = 3 first_name = Steve last_name = Seymour Customer: id = 4 first_name = Gail last_name = Williams Customer: id = 5 first_name = Doreen last_name = Heyson Updating customer 1 name to John Doe. Updating customer 1 name to Jean Smith. Customer: id = 1 first_name = Jean last_name = Smith Customer: id = 2 first_name = Cynthia last_name = Stevens Customer: id = 3 first_name = Steve last_name = Seymour Customer: id = 4 first_name = Gail last_name = Williams Customer: id = 5 first_name = Doreen last_name = Heyson
< BACKCONTINUE >

Index terms contained in this section

customers table
displayCustomers( ) method
first_name
last_name
main( ) method
multithreaded SQLJ programs
      designing
      JServer JVM
      MultithreadedExample1.sql
Oracle.connect( ) method
race condition
run( ) method
start( ) method
threads



Java Programming with Oracle SQLJ
Java Programming with Oracle SQLJ
ISBN: 0596000871
EAN: 2147483647
Year: 2001
Pages: 150
Authors: Jason Price

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net