项目需要,为了测试多线程能提高迁移数据的效率,写的一个小例子。不要问我为啥不用insert into testpstmt select * from dept;因为项目需要,不能用到该sql语句。
同时,只是和大家一起学习java多线程
/**
* 并发迁移数据
* 程序中表dept和表testpstmt结构一致
* @author ttan
*
*/
public class ConcurrentTransferData
{
public static int totalRowNum;
public static int index = 1;
public static volatile boolean isFinish;
static TaskThread[] taskThreads;
//总的线程个数,默认为1,多线程测试时,可以调整该值
private static final int THREAD_NUM = 1;
public static void main(String[] args) throws Exception
{
long startTime = System.currentTimeMillis();
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@192.168.5.201:1521:orcl";
String user = "scott";
String password = "tiger";
String sql = "select * from dept";
Connection conn = DriverManager.getConnection(url, user, password);
/**
* 读取
*/
Statement stmt = conn.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet rs = stmt.executeQuery(sql);
/**
* 写入
* 使用批处理
*/
PreparedStatement pstmt = null;
String psql = "insert into testpstmt values(?,?,?)";
pstmt = conn.prepareStatement(psql);
//rs.next 只要为true,说明表中记录数
rs.last();
totalRowNum = rs.getRow();
taskThreads = new TaskThread[THREAD_NUM];
TaskThread.initVariables(totalRowNum, pstmt);
int i = 0;
while (i < THREAD_NUM && !isFinish)
{
taskThreads[i] = new TaskThread(i, rs);
new Thread(taskThreads[i]).start();
i++;
}
//如果没完成,则主线程等待
while (!isFinish)
{
Thread.sleep(500);
}
pstmt.executeBatch();
conn.commit();
long endTime = System.currentTimeMillis();
System.out.println("整个迁移数据过程耗时:" + (endTime - startTime));
System.out.println("SUCCESS");
}
}
/**
* 并发迁移类
* @author ttan
*/
class TaskThread implements Runnable
{
int id;
static PreparedStatement pstmt = null;
ResultSet rs = null;
static int index = 1;
static int totalRowNum;
//已经结束任务的线程数
static int threadFlag;
//执行线程个数
static int threadNum;
public TaskThread(int id, ResultSet rs)
{
this.id = id;
//new一个线程,num++
threadNum++;
this.rs = rs;
}
@Override
public void run()
{
if (getExecuteNum() > totalRowNum)
{
setFinishTag();
return;
}
int index = incrementIndex();
//指定到具体的行数
try
{
while (index <= totalRowNum)
{
/**
* 同步控制ResultSet,确保在一个线程内,用的同一个结果集
*/
synchronized (rs)
{
System.out.println("index = " + index + this);
rs.absolute(index);
System.out.println(rs.getInt(1) + " " + this);
pstmt.setInt(1, rs.getInt(1));
pstmt.setString(2, rs.getString(2));
pstmt.setString(3, rs.getString(3));
pstmt.addBatch();
index = incrementIndex();
}
}
}
catch (SQLException e)
{
e.printStackTrace();
}
//每个run结束,表示一个线程执行结束,设置finish标志位,让threadFlg++
setFinishTag();
}
public static void initVariables(int totalNum, PreparedStatement p)
{
totalRowNum = totalNum;
threadFlag = 0;
pstmt = p;
}
public synchronized int incrementIndex()
{
return index++;
}
public synchronized int getExecuteNum()
{
return index;
}
/**
* 一个线程执行完后,设置标志位,判断时候所有的线程都执行完成
* 只有当所有的线程都执行完成,才设置标志位为true
*
* 表示一个表的记录迁移完成
*/
public synchronized void setFinishTag()
{
threadFlag++;
if (threadFlag == threadNum)
{
ConcurrentTransferData.isFinish = true;
}
}
@Override
public String toString()
{
return "thread : " + id;
}
}