import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class ConcurrentSelectForUpdate implements Runnable {
	public static final int NUM_WORKERS = 8;
	public static final String JDBC_URL = "jdbc:mysql://localhost/test";
	public static final String USER = "test";
	public static final String PASS = "test";
	private static volatile boolean condition = true;
	private Thread thread;

	public static void main(String[] args) {
		ConcurrentSelectForUpdate[] workers = new ConcurrentSelectForUpdate[NUM_WORKERS];

		for (int id = 0; id < NUM_WORKERS; id++) {
			workers[id] = new ConcurrentSelectForUpdate();
			workers[id].start();
		}
	}

	public void start() {
		if (thread == null) {
			this.thread = new Thread(this);
			thread.start();
		}
	}

	@Override
	public void run() {
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;

		try {
			conn = DriverManager.getConnection(JDBC_URL, USER, PASS);
			conn.setAutoCommit(false);
			stmt = conn.createStatement();

			while (condition) {
				rs = stmt
						.executeQuery("SELECT * FROM t WHERE id = 1 FOR UPDATE");

				while (rs.next()) {
				}

				rs.close();
				rs = stmt
						.executeQuery("SELECT * FROM t WHERE id = 2 FOR UPDATE");

				while (rs.next()) {
				}

				rs.close();
				conn.rollback();
			}
		} catch (SQLException e) {
			ConcurrentSelectForUpdate.condition = false;
			e.printStackTrace();
		} finally {
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException e2) {
				}
			}

			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e2) {
				}
			}

			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e2) {
				}
			}
		}
	}
}
