java怎么控制for循环内的程序等待IO读完数据?

我现在用jdbc程序往mysql插入十万条假数据,其中一种假数据的生成依赖io读取excel文件,再生成随机数拼接而成。
现在报空指针错误,我怀疑是因为假数据还没有生成,io时间长,for循环的赋值程序就进行了。
现在运行个3秒或4秒,就报空指针错误,一次只能插入200条数据,离目标很远。
我添加if语句判断假数据不为空才继续赋值,也不管用。
请问我该怎么控制啊?

public class AddXXXData {
    public static int  generateNum(int range){
        SecureRandom random = new SecureRandom();
        return  random.nextInt(range+1);
    }

    public static double  generateFloatNum(){
        double min = 1.0;
        double max = 200.0;
        double boundedDouble = min + new Random().nextDouble() * (max - min);
        return  boundedDouble;
    }

    public static String generateXXXname(){
        StringBuilder xxName = new StringBuilder();
        try {
            //创建工作簿对象
            XSSFWorkbook xssfWorkbook = new XSSFWorkbook(new FileInputStream("C:\\xx\\Desktop\\xx.xlsx"));
            XSSFSheet sheet = xssfWorkbook.getSheetAt(0);
            int maxRow = sheet.getLastRowNum();
            SecureRandom random = new SecureRandom();
            int i=random.nextInt(maxRow);

            XSSFWorkbook xssfWorkbook2 = new XSSFWorkbook(new FileInputStream("C:\\xx\\Desktop\\yy.xlsx"));
            XSSFSheet sheet2 = xssfWorkbook2.getSheetAt(0);
            int maxRow2 = sheet2.getLastRowNum();
            SecureRandom random2 = new SecureRandom();
            int j=random2.nextInt(maxRow2);

            xxName.append(sheet2.getRow(j-1).getCell(0)).append(sheet.getRow(i-1).getCell(0));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return  xxName.toString();
    }

    @Test
    public void add(){
        long stime = System.currentTimeMillis();
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            String url = "jdbc:mysql://xx.xx.xxx.xxx:3306/ss?characterEncoding=utf-8";
            String user = "xx";
            String password = "xx";
            conn = DriverManager.getConnection(url, user, password);
            for(int i=0;i<100000;i++){
                int id = generateNum(100);
                double num = generateFloatNum();
                String name = generateXXXname();

                if(name!=null){
                    Timestamp timestamp = new Timestamp(System.currentTimeMillis());
                    String sql = "INSERT INTO tb_xx (info,xx_name,aa_id,xx_picture," +
                            "price,num,status,bargin,zz_id,payment_count,insurance,free_delivery," +
                            "yy_id,created_time,updated_time) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
                    PreparedStatement ps = conn.prepareStatement(sql);
                    ps.setString(1," ");
                    ps.setString(2,name);
                    ps.setInt(3,id);
                    ps.setString(4," ");
                    ps.setDouble(5, num);
                    ps.setInt(6,100);
                    ps.setInt(7,1);
                    ps.setDouble(8,10.0);
                    ps.setInt(9,id);
                    ps.setInt(10,0);
                    ps.setString(11,"  ");
                    ps.setInt(12,1);
                    ps.setInt(13,id);
                    ps.setTimestamp(14,timestamp);
                    ps.setTimestamp(15,timestamp);
                    ps.executeUpdate();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        long etime = System.currentTimeMillis();
        System.out.printf("执行时长:%d 秒.", (etime - stime)/1000);
    }
}


可以尝试使用多线程来控制数据的生成和插入。将数据生成和插入分别放在不同的线程中,通过线程间的通信来控制数据的生成和插入速度。可以使用线程池来管理线程,避免线程过多导致系统资源的浪费。另外,也可以尝试优化数据生成和插入的代码,例如使用缓存来减少IO操作的次数,或者是使用批量插入来提高插入效率。最后,可以根据具体情况来调整数据生成和插入的速度,避免出现空指针错误。

多线程,主程序用事件量同步,运行完释放

该回答引用ChatGPT,希望能对你有帮助,你试试看看能不能解决问题
解决此问题的一种方法是在启动生成假数据的循环之前将 Excel 文件中的数据预加载到内存中。这样,您可以确保数据在需要时可用,并减少出现空指针错误的可能性。

下面是一个示例,说明如何修改类AddXXXData以从 Excel 文件预加载数据:

public class AddXXXData {
    private List<String> xxList;
    private List<String> yyList;

    public AddXXXData() {
        try {
            // Load data from xx.xlsx
            XSSFWorkbook xxWorkbook = new XSSFWorkbook(new FileInputStream("C:\\xx\\Desktop\\xx.xlsx"));
            XSSFSheet xxSheet = xxWorkbook.getSheetAt(0);
            int maxRow = xxSheet.getLastRowNum();
            xxList = new ArrayList<>(maxRow);
            for (int i = 0; i <= maxRow; i++) {
                String xx = xxSheet.getRow(i).getCell(0).getStringCellValue();
                xxList.add(xx);
            }

            // Load data from yy.xlsx
            XSSFWorkbook yyWorkbook = new XSSFWorkbook(new FileInputStream("C:\\xx\\Desktop\\yy.xlsx"));
            XSSFSheet yySheet = yyWorkbook.getSheetAt(0);
            maxRow = yySheet.getLastRowNum();
            yyList = new ArrayList<>(maxRow);
            for (int i = 0; i <= maxRow; i++) {
                String yy = yySheet.getRow(i).getCell(0).getStringCellValue();
                yyList.add(yy);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static int generateNum(int range) {
        SecureRandom random = new SecureRandom();
        return random.nextInt(range + 1);
    }

    public static double generateFloatNum() {
        double min = 1.0;
        double max = 200.0;
        double boundedDouble = min + new Random().nextDouble() * (max - min);
        return boundedDouble;
    }

    public String generateXXXname() {
        SecureRandom random = new SecureRandom();
        String xx = xxList.get(random.nextInt(xxList.size()));
        String yy = yyList.get(random.nextInt(yyList.size()));
        return xx + yy;
    }

    @Test
    public void add() {
        long stime = System.currentTimeMillis();
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            String url = "jdbc:mysql://xx.xx.xxx.xxx:3306/ss?characterEncoding=utf-8";
            String user = "xx";
            String password = "xx";
            conn = DriverManager.getConnection(url, user, password);

            // Load data from Excel files
            AddXXXData addXXXData = new AddXXXData();

            for (int i = 0; i < 100000; i++) {
                int id = generateNum(100);
                double num = generateFloatNum();
                String name = addXXXData.generateXXXname();

                if (name != null) {
                    Timestamp timestamp = new Timestamp(System.currentTimeMillis());
                    String sql = "INSERT INTO tb_xx (info,xx_name,aa_id,xx_picture," +
                            "price,num,status,bargin,zz_id,payment_count,insurance,free


参考GPT和自己的思路:

您可以将生成假数据的代码放在for循环外面,在循环内部等待直到读取完excel文件,然后再进行随机数的生成。同时,建议将读取excel文件的部分进行优化,使用缓存的方式将读取的数据存储起来,避免重复读取。另外,也可以使用多线程的方式进行处理,分离读取excel文件和生成随机数的操作,提高程序的执行效率。最后,也可以考虑使用批处理的方式一次插入多条数据,减少插入的时间。

io读数据的代码在哪呢
如果你希望读完再执行for循环,那你写顺序代码,不要多线程

把读取Excel操作放到for循环操作之前. 读取完在进行for循环

仅说空指针异常的问题,因为random.nextInt(maxRow)拿到了0,然后sheet.getRow(i-1)的时候取到了null,然后就空指针了。getRow里面的i和j不用减1就行了。