threadsafe.java

来自「PostgreSQL7.4.6 for Linux」· Java 代码 · 共 403 行

JAVA
403
字号
package example;import java.io.*;import java.sql.*;// rare in user code, but we use the LargeObject API in this testimport org.postgresql.largeobject.*;/* * This example tests the thread safety of the driver. * * It does this by performing several queries, in different threads. Each * thread has it's own Statement object, which is (in my understanding of the * jdbc specification) the minimum requirement. * */public class threadsafe{	Connection db;	// The connection to the database	Statement st;	// Our statement to run queries with	public threadsafe(String args[]) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException	{		String url = args[0];		String usr = args[1];		String pwd = args[2];		// Load the driver		Class.forName("org.postgresql.Driver");		// Connect to database		System.out.println("Connecting to Database URL = " + url);		db = DriverManager.getConnection(url, usr, pwd);		System.out.println("Connected...Now creating a statement");		st = db.createStatement();		// Clean up the database (in case we failed earlier) then initialise		cleanup();		// Because we use LargeObjects, we must use Transactions		db.setAutoCommit(false);		// Now run tests using JDBC methods, then LargeObjects		doexample();		// Clean up the database		cleanup();		// Finally close the database		System.out.println("Now closing the connection");		st.close();		db.close();	}	/*	 * This drops the table (if it existed). No errors are reported.	 */	public void cleanup()	{		try		{			st.executeUpdate("drop table basic1");		}		catch (Exception ex)		{			// We ignore any errors here		}		try		{			st.executeUpdate("drop table basic2");		}		catch (Exception ex)		{			// We ignore any errors here		}	}	/*	 * This performs the example	 */	public void doexample() throws SQLException	{		System.out.println("\nThis test runs three Threads. Two simply insert data into a table, then\nthey perform a query. While they are running, a third thread is running,\nand it load data into, then reads from a Large Object.\n\nIf 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 network\nconnection, and if locking on the stream isn't done correctly, the backend\nwill get pretty confused!\n");		thread3 thread3 = null;		try		{			// create the two threads			Thread thread0 = Thread.currentThread();			Thread thread1 = new thread1(db);			Thread thread2 = new thread2(db);			thread3 = new thread3(db);			// now run, and wait for them			thread1.start();			thread2.start();			thread3.start();			// ok, I know this is bad, but it does the trick here as our main thread			// will yield as long as either of the children are still running			System.out.println("Waiting for threads to run");			while (thread1.isAlive() || thread2.isAlive() || thread3.isAlive())				Thread.yield();		}		finally		{			// clean up after thread3 (the finally ensures this is run even			// if an exception is thrown inside the try { } construct)			if (thread3 != null)				thread3.cleanup();		}		System.out.println("No Exceptions have been thrown. This is a good omen, as it means that we are\npretty much thread safe as we can get.");	}	// This is the first thread. It's the same as the basic test	class thread1 extends Thread	{		Connection c;		Statement st;		public thread1(Connection c) throws SQLException		{			this.c = c;			st = c.createStatement();		}		public void run()		{			try			{				System.out.println("Thread 1 running...");				// First we need a table to store data in				st.executeUpdate("create table basic1 (a int2, b int2)");				// Now insert some data, using the Statement				st.executeUpdate("insert into basic1 values (1,1)");				st.executeUpdate("insert into basic1 values (2,1)");				st.executeUpdate("insert into basic1 values (3,1)");				// For large inserts, a PreparedStatement is more efficient, because it				// supports the idea of precompiling the SQL statement, and to store				// directly, a Java object into any column. PostgreSQL doesnt support				// precompiling, but does support setting a column to the value of a				// Java object (like Date, String, etc).				//				// Also, this is the only way of writing dates in a datestyle independent				// manner. (DateStyles are PostgreSQL's way of handling different methods				// of representing dates in the Date data type.)				PreparedStatement ps = db.prepareStatement("insert into basic1 values (?,?)");				for (int i = 2;i < 2000;i++)				{					ps.setInt(1, 4);		// "column a" = 5					ps.setInt(2, i);		// "column b" = i					ps.executeUpdate(); // executeUpdate because insert returns no data					//	  c.commit();					if ((i % 50) == 0)						DriverManager.println("Thread 1 done " + i + " inserts");				}				ps.close();			// Always close when we are done with it				// Finally perform a query on the table				DriverManager.println("Thread 1 performing a query");				ResultSet rs = st.executeQuery("select a, b from basic1");				int cnt = 0;				if (rs != null)				{					// Now we run through the result set, printing out the result.					// Note, we must call .next() before attempting to read any results					while (rs.next())					{						int a = rs.getInt("a"); // This shows how to get the value by name						int b = rs.getInt(2);	// This shows how to get the value by column						//System.out.println("  a="+a+" b="+b);						cnt++;					}					rs.close(); // again, you must close the result when done				}				DriverManager.println("Thread 1 read " + cnt + " rows");				// The last thing to do is to drop the table. This is done in the				// cleanup() method.				System.out.println("Thread 1 finished");			}			catch (SQLException se)			{				System.err.println("Thread 1: " + se.toString());				se.printStackTrace();				System.exit(1);			}		}	}	// This is the second thread. It's the similar to the basic test, and thread1	// except it works on another table.	class thread2 extends Thread	{		Connection c;		Statement st;		public thread2(Connection c) throws SQLException		{			this.c = c;			st = c.createStatement();		}		public void run()		{			try			{				System.out.println("Thread 2 running...");				// First we need a table to store data in				st.executeUpdate("create table basic2 (a int2, b int2)");				// For large inserts, a PreparedStatement is more efficient, because it				// supports the idea of precompiling the SQL statement, and to store				// directly, a Java object into any column. PostgreSQL doesnt support				// precompiling, but does support setting a column to the value of a				// Java object (like Date, String, etc).				//				// Also, this is the only way of writing dates in a datestyle independent				// manner. (DateStyles are PostgreSQL's way of handling different methods				// of representing dates in the Date data type.)				PreparedStatement ps = db.prepareStatement("insert into basic2 values (?,?)");				for (int i = 2;i < 2000;i++)				{					ps.setInt(1, 4);		// "column a" = 5					ps.setInt(2, i);		// "column b" = i					ps.executeUpdate(); // executeUpdate because insert returns no data					//	  c.commit();					if ((i % 50) == 0)						DriverManager.println("Thread 2 done " + i + " inserts");				}				ps.close();			// Always close when we are done with it				// Finally perform a query on the table				DriverManager.println("Thread 2 performing a query");				ResultSet rs = st.executeQuery("select * from basic2 where b>1");				int cnt = 0;				if (rs != null)				{					// First find out the column numbers.					//					// It's best to do this here, as calling the methods with the column					// numbers actually performs this call each time they are called. This					// really speeds things up on large queries.					//					int col_a = rs.findColumn("a");					int col_b = rs.findColumn("b");					// Now we run through the result set, printing out the result.					// Again, we must call .next() before attempting to read any results					while (rs.next())					{						int a = rs.getInt(col_a); // This shows how to get the value by name						int b = rs.getInt(col_b); // This shows how to get the value by column						//System.out.println("  a="+a+" b="+b);						cnt++;					}					rs.close(); // again, you must close the result when done				}				DriverManager.println("Thread 2 read " + cnt + " rows");				// The last thing to do is to drop the table. This is done in the				// cleanup() method.				System.out.println("Thread 2 finished");			}			catch (SQLException se)			{				System.err.println("Thread 2: " + se.toString());				se.printStackTrace();				System.exit(1);			}		}	}	// This is the third thread. It loads, then reads from a LargeObject, using	// our LargeObject api.	//	// The purpose of this is to test that FastPath will work in between normal	// JDBC queries.	class thread3 extends Thread	{		Connection c;		Statement st;		LargeObjectManager lom;		LargeObject lo;		int oid;		public thread3(Connection c) throws SQLException		{			this.c = c;			//st = c.createStatement();			// create a blob			lom = ((org.postgresql.PGConnection)c).getLargeObjectAPI();			oid = lom.create();			System.out.println("Thread 3 has created a blob of oid " + oid);		}		public void run()		{			try			{				System.out.println("Thread 3 running...");				DriverManager.println("Thread 3: Loading data into blob " + oid);				lo = lom.open(oid);				FileInputStream fis = new FileInputStream("example/threadsafe.java");				// keep the buffer size small, to allow the other thread a chance				byte buf[] = new byte[128];				int rc, bc = 1, bs = 0;				while ((rc = fis.read(buf)) > 0)				{					DriverManager.println("Thread 3 read block " + bc + " " + bs + " bytes");					lo.write(buf, 0, rc);					bc++;					bs += rc;				}				lo.close();				fis.close();				DriverManager.println("Thread 3: Reading blob " + oid);				lo = lom.open(oid);				bc = 0;				while (buf.length > 0)				{					buf = lo.read(buf.length);					if (buf.length > 0)					{						String s = new String(buf);						bc++;						DriverManager.println("Thread 3 block " + bc);						DriverManager.println("Block " + bc + " got " + s);					}				}				lo.close();				System.out.println("Thread 3 finished");			}			catch (Exception se)			{				System.err.println("Thread 3: " + se.toString());				se.printStackTrace();				System.exit(1);			}		}		public void cleanup() throws SQLException		{			if (lom != null && oid != 0)			{				System.out.println("Thread 3: Removing blob oid=" + oid);				lom.delete(oid);			}		}	}	/*	 * Display some instructions on how to run the example	 */	public static void instructions()	{		System.out.println("\nThis tests the thread safety of the driver.\n\nThis is done in two parts, the first with standard JDBC calls, and the\nsecond mixing FastPath and LargeObject calls with queries.\n");		System.out.println("Useage:\n java example.threadsafe jdbc:postgresql:database user password [debug]\n\nThe debug field can be anything. It's presence will enable DriverManager's\ndebug trace. Unless you want to see screens of items, don't put anything in\nhere.");		System.exit(1);	}	/*	 * This little lot starts the test	 */	public static void main(String args[])	{		System.out.println("PostgreSQL Thread Safety test v6.4 rev 1\n");		if (args.length < 3)			instructions();		// This line outputs debug information to stderr. To enable this, simply		// add an extra parameter to the command line		if (args.length > 3)			DriverManager.setLogStream(System.err);		// Now run the tests		try		{			threadsafe test = new threadsafe(args);		}		catch (Exception ex)		{			System.err.println("Exception caught.\n" + ex);			ex.printStackTrace();		}	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?