Java,多线程,ExecutorService

时间:2012-09-06 17:16:52

标签: java multithreading executorservice

以下是我的代码的一些部分,它使用了线程。目的是从数据库中检索所有记录(约5,00,000)并向其发送警报电子邮件。我面临的问题是变量emailRecords变得非常沉重,并且花费了太多时间来发送电子邮件消息。如何通过使用多线程快速实现,以便并行处理5,00,000条记录?我试图使用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 
        }
    }
}

3 个答案:

答案 0 :(得分:1)

使用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..

  }

 }

答案 1 :(得分:1)

据我所知,您很可能是单线程数据检索,并且多线程用于电子邮件发送。粗略地说,您将在结果集中循环并构建记录列表。当该列表达到特定大小时,您制作副本并发送该副本以在线程中处理,并清除原始列表。在结果集的末尾,检查列表中是否有未处理的记录,并将其发送到池中。

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

这些方面的东西:

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);
   }


}

答案 2 :(得分:0)

创建第二个线程来完成所有工作,而不是在主线程中执行相同的工作,这不会帮助您避免在处理之前填充{500}记录的emailRecords列表的问题他们中的任何一个。

听起来您的目标是能够从数据库中读取并并行发送电子邮件。不要担心代码,首先要考虑一个你想要完成的工作的算法。像这样:

  1. 在一个线程中,查询数据库中的记录,并为每个结果查找,将一个作业添加到ExecutorService
  2. 该职位向一个人/地址/记录发送电子邮件。
  3. 或者

    1. 从N(50,100,1000等)批次中读取数据库中的记录
    2. 将每个批次提交给executorService