请原谅任何错误的做法,因为我对线程很新。我有一个程序调用我的api并以json格式返回数据。每个请求都以json格式返回一行数据。总而言之,我需要每天检索大约2,000,000行,这意味着2,000,000个请求(我知道这是一个糟糕的设计,但系统不是为此设计的,这正是我在接下来的几周内需要做的)。当我尝试在单个线程上运行它时,我每分钟处理大约200个请求,这太慢了。结果我创建了12个线程,我每分钟处理5500行,这是一个很大的改进。问题是平均只有90%的行被插入到数据库中,因为我运行了几次以确保。在每个插入打印到文件之前,每个发送的URL然后我检查每个插入语句是否成功(执行时返回1),这一切似乎都很好。每次我运行它都会插入大约90%,但它确实有所不同,它从来都不是一致的数字。我在java代码中做错了吗?本质上,代码通过创建12个线程从main开始。每个线程创建一个run方法,该方法调用MySQLPopulateHistData的新实例,并传递一个开始和结束整数,这些整数在insert语句中用于范围。我做了很多system.out.println类型测试,可以看到所有线程都启动了,所有12个实例(每个线程的一个实例)都在执行?有谁知道它可能是什么?
MAIN:
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MainClass {
public static void main(String[] args) {
try {
//create a pool of threads
Thread[] threads = new Thread[12];
// submit jobs to be executing by the pool
for (int i = 0; i <12; i++) {
threads[i] = new Thread(new Runnable() {
public void run() {
try {
new MySQLPopulateHistData(RangeClass.IdStart, RangeClass.IdEnd);
} catch (Throwable e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
});
threads[i].start();
Thread.sleep(1000);
RangeClass.IdStart = RangeClass.IdEnd + 1;
RangeClass.IdEnd = RangeClass.IdEnd + 170000;
}
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
MyDataSourceFactory.class
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import javax.sql.DataSource;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
public class MyDataSourceFactory {
static String url = "jdbc:mysql://localhost:3306/my_schema";
static String userName = "root";
static String password = "password";
public synchronized static DataSource getMySQLDataSource() {
MysqlDataSource mysqlDS = null;
mysqlDS = new MysqlDataSource();
mysqlDS.setURL(url);
mysqlDS.setUser(userName);
mysqlDS.setPassword(password);
return mysqlDS;
}
}
MySQLPopulateHistData.class
public class MySQLPopulateHistData {
public MySQLPopulateHistData(int s, int e ) throws IOException, Throwable{
getHistory(s,e);
}
public synchronized void getHistory(int start, int end){
DataSource ds = MyDataSourceFactory.getMySQLDataSource();
Connection con = null;
Connection con2 = null;
Statement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try {
con = ds.getConnection();
con2 = ds.getConnection();
stmt = con.createStatement();
stmt2 = con.createStatement();
rs = stmt.executeQuery("SELECT s FROM sp_t where s_id BETWEEN "+ start +" AND "+ end + " ORDER BY s;");
String s = "";
while(rs.next()){
s = rs.getString("s");
if( s == ""){
}
else{
try{
URL fullUrl = new URL(//My Url to my api with password with start and end range);
InputStream is = fullUrl.openStream();
String jsonStr = getStringFromInputStream(is);
JSONObject j = new JSONObject(jsonStr);
JSONArray arr = j.getJSONObject("query").getJSONObject("results").getJSONArray("quote");
for(int i=0; i<arr.length(); i++){
JSONObject obj = arr.getJSONObject(i);
String symbol = obj.getString("s");
stmt2.executeUpdate("INSERT into sp2_t(s) VALUES ('"+ s +"') BETWEEN "+start+" AND "+ end +";");
}
}
catch(Exception e){
}
}
s = "";
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
if(rs != null) rs.close();
if(stmt != null) stmt.close();
if(con != null) con.close();
if(stmt2 != null) stmt.close();
if(con2 != null) con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
更新
所以我说:
(if s.equals("")){
System.out.println("EMPTY");
}
它从未打印出EMPTY。在JSON请求转换为JSONArray之后,我添加了:
if(arr.length()>0){
StaticClassHolder.cntResponses++;
}
这只是另一个类中的静态变量,每当有一个有效的JSON响应时它就会递增。它等于它应该是的确切数量。所以似乎URL正确获取所有响应,正确解析它们,但是没有将它们正确地插入到数据库中?我想不通为什么?
答案 0 :(得分:0)
在Oracle中插入记录时,我也遇到了类似的问题。由于我没有找到任何具体的解决方案。我试过单线程,一切都很顺利。
答案 1 :(得分:-1)
为什么这不起作用有几个原因:
普通计算机每个CPU只能处理大约4-8个线程。由于系统使用某些线程,因此您只能同时运行某些线程。计算机通过暂停某些线程然后运行另一个线程来处理此问题。
如果您尝试通过套接字向mysql服务器发送多个查询,同时有些请求将无效,您将丢失部分数据。
至于现在,我没有任何解决方案来更快地更新表格。