threadsafe.java
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:11k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. package example;
  2. import java.io.*;
  3. import java.sql.*;
  4. import java.text.*;
  5. // rare in user code, but we use the LargeObject API in this test
  6. import postgresql.largeobject.*;
  7. /**
  8.  * This example tests the thread safety of the driver.
  9.  *
  10.  * It does this by performing several queries, in different threads. Each
  11.  * thread has it's own Statement object, which is (in my understanding of the
  12.  * jdbc specification) the minimum requirement.
  13.  *
  14.  */
  15. public class threadsafe
  16. {
  17.   Connection db; // The connection to the database
  18.   Statement  st; // Our statement to run queries with
  19.   
  20.   public threadsafe(String args[]) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
  21.   {
  22.     String url = args[0];
  23.     String usr = args[1];
  24.     String pwd = args[2];
  25.     
  26.     // Load the driver
  27.     Class.forName("postgresql.Driver");
  28.     
  29.     // Connect to database
  30.     System.out.println("Connecting to Database URL = " + url);
  31.     db = DriverManager.getConnection(url, usr, pwd);
  32.     
  33.     System.out.println("Connected...Now creating a statement");
  34.     st = db.createStatement();
  35.     
  36.     // Clean up the database (in case we failed earlier) then initialise
  37.     cleanup();
  38.     
  39.     // Now run tests using JDBC methods, then LargeObjects
  40.     doexample();
  41.     
  42.     // Clean up the database
  43.     cleanup();
  44.     
  45.     // Finally close the database
  46.     System.out.println("Now closing the connection");
  47.     st.close();
  48.     db.close();
  49.     
  50.   }
  51.   
  52.   /**
  53.    * This drops the table (if it existed). No errors are reported.
  54.    */
  55.   public void cleanup()
  56.   {
  57.     try {
  58.       st.executeUpdate("drop table basic");
  59.     } catch(Exception ex) {
  60.       // We ignore any errors here
  61.     }
  62.   }
  63.   
  64.   /**
  65.    * This performs the example
  66.    */
  67.   public void doexample() throws SQLException
  68.   {
  69.     System.out.println("nThis test runs three Threads. Two simply insert data into a table, thennthey perform a query. While they are running, a third thread is running,nand it load data into, then reads from a Large Object.nnIf alls well, this should run without any errors. If so, we are Thread Safe.nWhy test JDBC & LargeObject's? Because both will run over the networknconnection, and if locking on the stream isn't done correctly, the backendnwill get pretty confused!n");
  70.     
  71.     thread3 thread3=null;
  72.     
  73.     try {
  74.       
  75.       // create the two threads
  76.       Thread thread0 = Thread.currentThread();
  77.       Thread thread1 = new thread1(db);
  78.       Thread thread2 = new thread2(db);
  79.       thread3 = new thread3(db);
  80.       
  81.       // now run, and wait for them
  82.       thread1.start();
  83.       thread2.start();
  84.       thread3.start();
  85.       
  86.       // ok, I know this is bad, but it does the trick here as our main thread
  87.       // will yield as long as either of the children are still running
  88.       System.out.println("Waiting for threads to run");
  89.       while(thread1.isAlive() || thread2.isAlive() || thread3.isAlive())
  90. thread0.yield();
  91.       
  92.     } finally {
  93.       // clean up after thread3 (the finally ensures this is run even
  94.       // if an exception is thrown inside the try { } construct)
  95.       if(thread3 != null)
  96. thread3.cleanup();
  97.     }
  98.     
  99.     System.out.println("No Exceptions have been thrown. This is a good omen, as it means that we arenpretty much thread safe as we can get.");
  100.   }
  101.   
  102.   // This is the first thread. It's the same as the basic test
  103.   class thread1 extends Thread
  104.   {
  105.     Connection c;
  106.     Statement st;
  107.     
  108.     public thread1(Connection c) throws SQLException {
  109.       this.c = c;
  110.       st = c.createStatement();
  111.     }
  112.     
  113.     public void run() {
  114.       try {
  115. System.out.println("Thread 1 running...");
  116. // First we need a table to store data in
  117. st.executeUpdate("create table basic (a int2, b int2)");
  118. // Now insert some data, using the Statement
  119. st.executeUpdate("insert into basic values (1,1)");
  120. st.executeUpdate("insert into basic values (2,1)");
  121. st.executeUpdate("insert into basic values (3,1)");
  122. // For large inserts, a PreparedStatement is more efficient, because it
  123. // supports the idea of precompiling the SQL statement, and to store
  124. // directly, a Java object into any column. PostgreSQL doesnt support
  125. // precompiling, but does support setting a column to the value of a
  126. // Java object (like Date, String, etc).
  127. //
  128. // Also, this is the only way of writing dates in a datestyle independent
  129. // manner. (DateStyles are PostgreSQL's way of handling different methods
  130. // of representing dates in the Date data type.)
  131. PreparedStatement ps = db.prepareStatement("insert into basic values (?,?)");
  132. for(int i=2;i<200;i++) {
  133.   ps.setInt(1,4); // "column a" = 5
  134.   ps.setInt(2,i); // "column b" = i
  135.   ps.executeUpdate(); // executeUpdate because insert returns no data
  136.   if((i%50)==0)
  137.     DriverManager.println("Thread 1 done "+i+" inserts");
  138. }
  139. ps.close(); // Always close when we are done with it
  140. // Finally perform a query on the table
  141. DriverManager.println("Thread 1 performing a query");
  142. ResultSet rs = st.executeQuery("select a, b from basic");
  143. int cnt=0;
  144. if(rs!=null) {
  145.   // Now we run through the result set, printing out the result.
  146.   // Note, we must call .next() before attempting to read any results
  147.   while(rs.next()) {
  148.     int a = rs.getInt("a"); // This shows how to get the value by name
  149.     int b = rs.getInt(2); // This shows how to get the value by column
  150.     //System.out.println("  a="+a+" b="+b);
  151.     cnt++;
  152.   }
  153.   rs.close(); // again, you must close the result when done
  154. }
  155. DriverManager.println("Thread 1 read "+cnt+" rows");
  156. // The last thing to do is to drop the table. This is done in the
  157. // cleanup() method.
  158. System.out.println("Thread 1 finished");
  159.       } catch(SQLException se) {
  160. System.err.println("Thread 1: "+se.toString());
  161. se.printStackTrace();
  162. System.exit(1);
  163.       }
  164.     }
  165.   }
  166.   
  167.   // This is the second thread. It's the similar to the basic test, and thread1
  168.   // except it works on another table.
  169.   class thread2 extends Thread
  170.   {
  171.     Connection c;
  172.     Statement st;
  173.     
  174.     public thread2(Connection c) throws SQLException {
  175.       this.c = c;
  176.       st = c.createStatement();
  177.     }
  178.     
  179.     public void run() {
  180.       try {
  181. System.out.println("Thread 2 running...");
  182. // For large inserts, a PreparedStatement is more efficient, because it
  183. // supports the idea of precompiling the SQL statement, and to store
  184. // directly, a Java object into any column. PostgreSQL doesnt support
  185. // precompiling, but does support setting a column to the value of a
  186. // Java object (like Date, String, etc).
  187. //
  188. // Also, this is the only way of writing dates in a datestyle independent
  189. // manner. (DateStyles are PostgreSQL's way of handling different methods
  190. // of representing dates in the Date data type.)
  191. PreparedStatement ps = db.prepareStatement("insert into basic values (?,?)");
  192. for(int i=2;i<200;i++) {
  193.   ps.setInt(1,4); // "column a" = 5
  194.   ps.setInt(2,i); // "column b" = i
  195.   ps.executeUpdate(); // executeUpdate because insert returns no data
  196.   if((i%50)==0)
  197.     DriverManager.println("Thread 2 done "+i+" inserts");
  198. }
  199. ps.close(); // Always close when we are done with it
  200. // Finally perform a query on the table
  201. DriverManager.println("Thread 2 performing a query");
  202. ResultSet rs = st.executeQuery("select * from basic where b>1");
  203. int cnt=0;
  204. if(rs!=null) {
  205.   // First find out the column numbers.
  206.   //
  207.   // It's best to do this here, as calling the methods with the column
  208.   // numbers actually performs this call each time they are called. This
  209.   // really speeds things up on large queries.
  210.   //
  211.   int col_a = rs.findColumn("a");
  212.   int col_b = rs.findColumn("b");
  213.   
  214.   // Now we run through the result set, printing out the result.
  215.   // Again, we must call .next() before attempting to read any results
  216.   while(rs.next()) {
  217.     int a = rs.getInt(col_a); // This shows how to get the value by name
  218.     int b = rs.getInt(col_b); // This shows how to get the value by column
  219.     //System.out.println("  a="+a+" b="+b);
  220.     cnt++;
  221.   }
  222.   rs.close(); // again, you must close the result when done
  223. }
  224. DriverManager.println("Thread 2 read "+cnt+" rows");
  225. // The last thing to do is to drop the table. This is done in the
  226. // cleanup() method.
  227. System.out.println("Thread 2 finished");
  228.       } catch(SQLException se) {
  229. System.err.println("Thread 2: "+se.toString());
  230. se.printStackTrace();
  231. System.exit(1);
  232.       }
  233.     }
  234.   }
  235.   
  236.   // This is the third thread. It loads, then reads from a LargeObject, using
  237.   // our LargeObject api.
  238.   //
  239.   // The purpose of this is to test that FastPath will work in between normal
  240.   // JDBC queries.
  241.   class thread3 extends Thread
  242.   {
  243.     Connection c;
  244.     Statement st;
  245.     LargeObjectManager lom;
  246.     LargeObject lo;
  247.     int oid;
  248.     
  249.     public thread3(Connection c) throws SQLException {
  250.       this.c = c;
  251.       //st = c.createStatement();
  252.       
  253.       // create a blob
  254.       lom = ((postgresql.Connection)c).getLargeObjectAPI();
  255.       oid = lom.create();
  256.       System.out.println("Thread 3 has created a blob of oid "+oid);
  257.     }
  258.     
  259.     public void run() {
  260.       try {
  261. System.out.println("Thread 3 running...");
  262. DriverManager.println("Thread 3: Loading data into blob "+oid);
  263. lo = lom.open(oid);
  264. FileInputStream fis = new FileInputStream("example/threadsafe.java");
  265. // keep the buffer size small, to allow the other thread a chance
  266. byte buf[] = new byte[128];
  267. int rc,bc=1,bs=0;
  268. while((rc=fis.read(buf))>0) {
  269.   DriverManager.println("Thread 3 read block "+bc+" "+bs+" bytes");
  270.   lo.write(buf,0,rc);
  271.   bc++;
  272.   bs+=rc;
  273. }
  274. lo.close();
  275. fis.close();
  276. DriverManager.println("Thread 3: Reading blob "+oid);
  277. lo=lom.open(oid);
  278. bc=0;
  279. while(buf.length>0) {
  280.   buf=lo.read(buf.length);
  281.   if(buf.length>0) {
  282.     String s = new String(buf);
  283.     bc++;
  284.     DriverManager.println("Thread 3 block "+bc);
  285.     DriverManager.println("Block "+bc+" got "+s);
  286.   }
  287. }
  288. lo.close();
  289. System.out.println("Thread 3 finished");
  290.       } catch(Exception se) {
  291. System.err.println("Thread 3: "+se.toString());
  292. se.printStackTrace();
  293. System.exit(1);
  294.       }
  295.     }
  296.     
  297.     public void cleanup() throws SQLException {
  298.       if(lom!=null && oid!=0) {
  299. System.out.println("Thread 3: Removing blob oid="+oid);
  300. lom.delete(oid);
  301.       }
  302.     }
  303.   }
  304.   
  305.   /**
  306.    * Display some instructions on how to run the example
  307.    */
  308.   public static void instructions()
  309.   {
  310.     System.out.println("nThis tests the thread safety of the driver.nnThis is done in two parts, the first with standard JDBC calls, and thensecond mixing FastPath and LargeObject calls with queries.n");
  311.     System.out.println("Useage:n java example.threadsafe jdbc:postgresql:database user password [debug]nnThe debug field can be anything. It's presence will enable DriverManager'sndebug trace. Unless you want to see screens of items, don't put anything innhere.");
  312.     System.exit(1);
  313.   }
  314.   
  315.   /**
  316.    * This little lot starts the test
  317.    */
  318.   public static void main(String args[])
  319.   {
  320.     System.out.println("PostgreSQL Thread Safety test v6.4 rev 1n");
  321.     
  322.     if(args.length<3)
  323.       instructions();
  324.     
  325.     // This line outputs debug information to stderr. To enable this, simply
  326.     // add an extra parameter to the command line
  327.     if(args.length>3)
  328.       DriverManager.setLogStream(System.err);
  329.     
  330.     // Now run the tests
  331.     try {
  332.       threadsafe test = new threadsafe(args);
  333.     } catch(Exception ex) {
  334.       System.err.println("Exception caught.n"+ex);
  335.       ex.printStackTrace();
  336.     }
  337.   }
  338. }