我希望有人可以帮助我,我很擅长使用线程,我需要做的是在我的代码中放入一个标志,以便在完成所有线程时通知然后调用更新表的方法将其标记为已完成。我已经阅读了很多关于执行器框架的内容,但我不知道如何实现它。
这是我的代码:
public static void main(String[] args) throws SQLException {
LOG.info(args.length);
LOG.info("Args = " + args);
if (args != null && args.length > 0 && args[0] != null && args[0].equals("stop")) {
stop(args);
} else {
new Thread(new PayatReconService()).start();
LOG.info("This is after the main method");
}
}
static void stop(String[] args) {
LOG.info("STOPPING SERVER!");
// Need to stop all TimerTasks here
running = false;
try {
// sleep for a second, allow threads to close
Thread.sleep(1000);
} catch (InterruptedException ex) {
LOG.info("exception " + ex.getMessage());
}
System.exit(0);
}
@Override
public void run() {
running = true;
PayatReconService reconService = new PayatReconService();
try {
mailingQueue = new MailingQueue(prop);
LOG.info("Starting Recon Service");
ProcessRecon pr = new ProcessRecon();
//Starts startRecon method in processRecon class
pr.startRecon();
} catch (Exception ex) {
LOG.error(ex, ex);
}
}
}
ProcessRecon.java:
public void startRecon() throws SQLException {
//log starting recon
loadRetailers();
}
public void loadRetailers() throws SQLException {
DB db = new DB();
try (Connection con = db.getConnection(); PreparedStatement loadSt = con.prepareStatement(DB.LOAD_RETAILERS)){
PayatReconService.LOG.info("Load Retailers");
rs = loadSt.executeQuery();
while (rs.next()) {
Retailer r = new Retailer();
//Retrieve retailer information from company table
r.setFtpFolder(rs.getString("ftp_folder"));
r.setFtpPassword(rs.getString("ftp_password"));
r.setFtpUsername(rs.getString("ftp_username"));
r.setIsAutoRecon(rs.getBoolean("autorecon"));
r.setIsSFTP(rs.getBoolean("sftp"));
r.setReconFolder(rs.getString("reconfolder"));
r.setRemoteFTPFolder(rs.getString("remoteftphost"));
r.setRemoteFTPPassword(rs.getString("remoteftppassword"));
r.setRemoteFTPUsername(rs.getString("remoteftpusername"));
r.setReportPrefix(rs.getString("reportprefix"));
r.setRetailID(rs.getString("recid"));
r.setName(rs.getString("name"));
new Thread(r).start();
}
} catch (Exception ex) {
System.out.println(ex.getMessage());
PayatReconService.LOG.info(ex.getMessage());
}
}
}
因此,在此类中,它从数据库中检索所有信息并将其链接到Retailer类上的线程,一旦检索到所有信息,它就会激活run方法。
Retailer.java:
@Override
public void run() {
try {
Thread thread = Thread.currentThread();
thread.setName(getName()); // Set thread name
System.out.println("RunnableJob is being run by " + thread.getName() + " (" + thread.getId() + ")");
PayatReconService.LOG.info("RunnableJob is being run by " + thread.getName() + " (" + thread.getId() + ")");
DB db = new DB();
try (Connection con = db.getConnection(); Statement st = con.createStatement()){
while (PayatReconService.running) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(Retailer.class.getName()).log(Level.SEVERE, null, ex);
}
PayatReconService.LOG.info("Check if allowed to run");
if (canRun()) {
PayatReconService.LOG.info("Run approved");
searchReconFile();
// the flag needs to be here to indicate that all the threads are done running
System.out.println("Mark table as complete");
markasComplete();
PayatReconService.LOG.info("Waiting to rerun");
//wait 5min before trying again
Thread.sleep(300000);
PayatReconService.LOG.info("Go");
} else {
Thread.sleep(300000);
}
}
} catch (Exception e) {
//sql connect error
System.out.println(e.getMessage());
PayatReconService.LOG.info(e.getMessage());
setErrors("01");
}
} catch (SQLException ex) {
Logger.getLogger(Retailer.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void markasComplete() throws SQLException {
PayatReconService.LOG.info("Update tblPay@Timers as complete.");
DB db = new DB();
try (Connection con = db.getConnection(); Statement st = con.createStatement()){
String sql;
sql = " update tblpay@timers set scheduled = 0 "
+ " where timertype in ('recon_new')";
st.executeUpdate(sql);
} catch (SQLException e) {
PayatReconService.LOG.error(e.getMessage());
}
}
所以在markasComplete()可以运行之前,所有线程都应该先完成然后更新表,如果有人可以帮助我那会很棒或者指出我正确的方向。
由于
答案 0 :(得分:0)
有两种方法 - 最好的方法是使用一个锁存器,例如这个代码启动10个任务,另一个代码在它们全部完成时运行:
public void test1() throws InterruptedException {
final ExecutorService service = Executors.newFixedThreadPool(5);
final CountDownLatch latch = new CountDownLatch(10);
for(int i = 0; i < 10; i++) {
final int threadId = i;
Callable<?> c = new Callable<Object>() {
@Override
public Object call() throws Exception {
long waitUntil = (long) (System.currentTimeMillis() + (Math.random() * 5000));
while(System.currentTimeMillis() < waitUntil);
latch.countDown();
System.out.println("Finished task " + threadId);
return null;
}
};
service.submit(c);
}
// Start a thread which will run when the others are finished.
new Thread(new Runnable() {
@Override
public void run() {
try { latch.await(); } catch (InterruptedException e) { }
System.out.println("All finished");
}
}).start();
// Carry on main thread....
Thread.sleep(60000);
}
当然,您可以关闭执行程序服务并等待它完成,在这种情况下,您不需要锁存器,通过将最后一个线程替换为:
new Thread(new Runnable() {
@Override
public void run() {
service.shutdown();
try { service.awaitTermination(10, TimeUnit.DAYS); } catch (InterruptedException e) { }
System.out.println("All finished");
}
}).start();