我现在用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就行了。