Java 并发将oracle表中记录利用JDBC迁移到同结构的另一个表中

项目需要,为了测试多线程能提高迁移数据的效率,写的一个小例子。不要问我为啥不用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;
    }
}


你可能感兴趣的:(Java 并发将oracle表中记录利用JDBC迁移到同结构的另一个表中)