Java,多线程,执行程序服务



下面是我的代码的一些部分,它使用线程。目的是从数据库中检索所有记录(约500000),并向它们发送警报电子邮件。我面临的问题是可变的电子邮件记录变得非常重,发送电子邮件需要花费太多时间。如何使用多线程来快速处理500000条记录?我试着使用ExecutorService,但在实现过程中遇到了困惑。我混淆了checkName()、getRecords()和sendAlert()方法。这三种方法都是有关联的。那么,在哪里使用executorService??

请向我提供如何处理以下代码的建议,以及哪些部分需要编辑?提前感谢!!

public class sampledaemon implements Runnable {
    private static List<String[]> emailRecords = new ArrayList<String[]>();
    public static void main(String[] args) {
        if (args.length != 1) {
            return;
        }
        countryName = args[0];
        try {
            Thread t = null;
            sampledaemon daemon = new sampledaemon();
            t = new Thread(daemon);
            t.start();
        } catch (Exception e) {
            e.printStackTrace()
        }
    }
    public void run() {
        Thread thisThread = Thread.currentThread();
        try {
            while (true) {
                checkName(countryName);
                Thread.sleep(TimeUnit.SECONDS.toMillis(10));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void checkName(String countryName) throws Exception {
        Country country = CountryPojo.getDetails(countryName)
        if (country != null) {
            getRecords(countryconnection);
        }
    }
    private void getRecords(Country country, Connection con) {
        String users[] = null;
        while (rs.next()) {
            users = new String[2];
            users[0] = rs.getString("userid");
            users[1] = rs.getString("emailAddress");
            emailRecords.add(props);
            if (emailRecords.size() > 0) {
                sendAlert(date, con);
            }
        }
    }
    void sendAlert(String date, Connection con) {
        for (int k = 0; k < emailRecords.size(); k++) {
            //check the emailRecords and send email 
        }
    }
}

根据我的判断,您很可能是单线程数据检索,而电子邮件发送则是多线程的。大致来说,你会循环浏览你的结果集,并建立一个记录列表。当该列表达到一定大小时,您可以制作一个副本,并将该副本发送到线程中进行处理,然后清除原始列表。在结果集的末尾,检查列表中是否有未处理的记录,并将其发送到池中。

最后,等待线程池完成对所有记录的处理。

大致如下:

protected void processRecords(String countryName) {
  ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 10, TimeUnit.SECONDS, 
        new ArrayBlockingQueue<Runnable>(5), new ThreadPoolExecutor.CallerRunsPolicy());
   List<String[]> emaillist = new ArrayList<String>(1000);
   ResultSet rs = ....
   try {
     while (rs.next()) {
        String user[] = new String[2];
        users[0] = rs.getString("userid");
        users[1] = rs.getString("emailAddress");
        emaillist.add(user);
        if (emaillist.size() == 1000) {
            final List<String[]> elist = new ArrayList<String[]>(emaillist);
            executor.execute(new Runnable() {
                public void run() {
                    sendMail(elist);
                }
            }
            emaillist.clear();
        }
     }
   }
   finally {
     DbUtils.close(rs);
   }
   if (! emaillist.isEmpty()) {
            final List<String[]> elist = emaillist;
            executor.execute(new Runnable() {
                public void run() {
                    sendMail(elist);
                }
            }
            emaillist.clear();
   }
   // wait for all the e-mails to finish.
   while (! executor.isTerminated()) {
       executor.shutdown();
       executor.awaitTermination(10, TimeUnit.DAYS);
   }

}

使用FixedThreadPool的优势在于,您不必执行一次又一次创建线程的昂贵过程,它在开始时就完成了。。。见下文。。

ExecutorService executor = Executors.newFixedThreadPool(100);
ArrayList<String> arList =  Here your Email addresses from DB will go in ;
for(String s : arList){
     executor.execute(new EmailAlert(s));
 }

public class EmailAlert implements Runnable{
  String addr;
   public EmailAlert(String eAddr){

         this.addr = eAddr;
       }

  public void run(){

     // Do the process of sending the email here..
  }
 }

创建第二个线程来执行中的所有工作,而不是在主线程中执行相同的工作,这并不能帮助您避免在处理任何记录之前用500万条记录填充emailRecords列表的问题。

听起来你的目标是能够同时读取数据库和发送电子邮件。与其担心代码,不如先为你想要完成的工作考虑一个算法。类似这样的东西:

  1. 在一个线程中,查询数据库中的记录,对于每个结果,向ExecutiorService添加一个作业
  2. 该工作会向一个人/地址/记录发送电子邮件

或者

  1. 以N(50、100、1000等)为一批从数据库中读取记录
  2. 将每批提交给executeService

相关内容

  • 没有找到相关文章

最新更新