摘要:郵件信息發件人信息每個線程發送郵件的最大數量去除重復的收件人存儲發送失敗的收件人存儲發送成功的收件人記錄發送郵件的次數每個收件人創建一個線程用來發送郵件處理結果
前言
之前用java mail發送郵件,都是分給每個郵件一個線程,在郵件發送成功后,由該子線程將mail的信息(發送成功的郵箱和未發送的郵箱)存儲到數據庫中。
現在需要處理一封郵件有上萬收件人的情況,如果還按照之前每個mail一個線程,發送的效率太低了,因此需要將一封郵件分到多個線程中去執行,讓每個子線程處理一部分收件人,但是子線程執行完成后更新mail的信息,會出現數據覆蓋的情況。
如果每個子線程執行完后能將發送郵件的信息返回給主線程,那么我們就可以在所有子線程結束后再存儲mail的信息了。
Java CallableRunnable任務不返回任何值,如果你希望在任務完成時能夠返回一個值,那么可以實現Callable接口而不是Runnable接口,Callable是一種具有類型參數的泛型,它的類型參數表示的是從方法call()中返回的值,并且必須使用ExecutorService.submit()方法調用它。
public class TaskWithResult implements Callable{ @Override public String call() throws Exception { return "result"; } } public class TaskDemo{ public static void main(String[] args) { ExecutorService exec = Executors.newCachedThreadPool(); TaskWithResult task = new TaskWithResult(); Future future = exec.submit(task); try { System.out.println(future.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } } /* Output: result */
submit()方法會產生Future對象,你可以用isDone()來查詢Future是否已經完成,任務完成時,可以用get()方法獲取任務的返回值,如果任務沒有完成,調用get()方法會阻塞主線程。
代碼實現在獲取返回結果時,get()會阻塞主線程,為了使發送郵件的函數不被阻塞,我們需要新創建一個線程來運行發送郵件的子線程。
類Mailer為實現了Callable的發送郵件的具體實現的代碼。Mail為郵件的實體。
public class MailerTask extends Thread { private Mail mail;//郵件信息 private String sender;//發件人信息 //每個線程發送郵件的最大數量 private static final int mail_limit = 100; public static void send(Mail mail, String sender){ MailerTask mailerTask = new MailerTask(); mailerTask.setMail(mail); mailerTask.setSender(sender); mailerTask.start(); } @Override public void run() { ExecutorService exec = Executors.newFixedThreadPool(20); // 去除重復的收件人 ListsendTos = Arrays.stream(mail.getSendTo().split(";")).distinct().collect(Collectors.toList()); // 存儲發送失敗的收件人 String sendTo = ""; // 存儲發送成功的收件人 String sended = ""; // 記錄發送郵件的次數 int sendTimes = 0; Mailer.setSender(sender); List >> futures = new ArrayList<>(); // 每100個收件人創建一個線程用來發送郵件 for (int i = 0; i <= sendTos.size()/mail_limit; i++ ){ List subSendTos = sendTos.stream().skip(i*mail_limit).limit(mail_limit).collect(Collectors.toList()); String subSendTo = subSendTos.stream().collect(Collectors.joining(";")); mail.setSendTo(subSendTo); Mailer mailer = new Mailer(); mailer.setMail(mail); Future > result = exec.submit(mailer); futures.add(result); } // 處理結果 for (Future
> future : futures){ try { String subSendTo = future.get().get(0); String subSended = future.get().get(1); String subtimes = future.get().get(2); if (subSendTo != "") { sendTo = sendTo + subSendTo + ";"; } if (subSended != "" && subSended != null) { sended += subSended; sended += ";"; } sendTimes += Integer.valueOf(subtimes); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } exec.shutdown(); mail.setSendTo(sendTo); mail.setSended(sended); mail.setSendTimes(sendTimes); mail.setFinishDate(sendTo.isEmpty() ? new Date() : null); MailService mailService = (MailService) ServiceFactory.getSpringBean("mailService"); mailService.saveMail(mail); } public void setSender(String sender) { this.sender = sender; } public void setMail(Mail mail) { this.mail = mail; } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67656.html
摘要:函數攜帶目的地址主題郵件體模板和一組關鍵字參數。許多擴展操作是在假設有活動的應用程序和請求上下文的情況下進行的。但是當函數在一個不同的線程上執行,應用程序上下文需要人為地創建使用。例如,執行函數可以將郵件發送到的任務隊列中。 許多類型的應用程序都會在某些事件發生的時候通知用戶,常用的溝通方法就是電子郵件。盡管在Flask應用程序中,可以使用Python標準庫中的smtplib包來發送電...
摘要:網上也有不少人反饋用手機客戶端無法使用新浪郵箱發送郵件,隨后我嘗試用登錄新浪郵箱,也出現只能接收郵件而不能發送郵件的情況。三附錄錯誤碼及建議解決方法發送郵件成功卻收不到郵件或收到郵件無主題無收件人亂碼新浪郵箱誠信平臺 前言 ??JavaMail的使用本身并不難,網上有不少案例,簡單易懂,而且有詳細的中文注解。但是由于JavaMail的機制設置不夠完善,特別是異常出錯時的參考信息太少,給...
摘要:我拿網易郵箱賬號舉例子,那么我們如何才能讓你的郵箱賬號可以利用第三方發送郵件這里的第三方就是我們即將編寫的程序。 一 前言 測試所使用的環境 測試使用的環境是企業主流的SSM 框架即 SpringMVC+Spring+Mybatis。為了節省時間,我直接使用的是我上次的SSM項目中整合Echarts開發該項目已經搭建完成的SSM環境。 標題說的四種姿勢指的是哪四種姿勢? 發送text...
閱讀 2597·2021-10-14 09:43
閱讀 3559·2021-10-13 09:39
閱讀 3289·2019-08-30 15:44
閱讀 3137·2019-08-29 16:37
閱讀 3702·2019-08-29 13:17
閱讀 2731·2019-08-26 13:57
閱讀 1825·2019-08-26 11:59
閱讀 1238·2019-08-26 11:46