摘要:郵件信息發(fā)件人信息每個(gè)線程發(fā)送郵件的最大數(shù)量去除重復(fù)的收件人存儲(chǔ)發(fā)送失敗的收件人存儲(chǔ)發(fā)送成功的收件人記錄發(fā)送郵件的次數(shù)每個(gè)收件人創(chuàng)建一個(gè)線程用來(lái)發(fā)送郵件處理結(jié)果
前言
之前用java mail發(fā)送郵件,都是分給每個(gè)郵件一個(gè)線程,在郵件發(fā)送成功后,由該子線程將mail的信息(發(fā)送成功的郵箱和未發(fā)送的郵箱)存儲(chǔ)到數(shù)據(jù)庫(kù)中。
現(xiàn)在需要處理一封郵件有上萬(wàn)收件人的情況,如果還按照之前每個(gè)mail一個(gè)線程,發(fā)送的效率太低了,因此需要將一封郵件分到多個(gè)線程中去執(zhí)行,讓每個(gè)子線程處理一部分收件人,但是子線程執(zhí)行完成后更新mail的信息,會(huì)出現(xiàn)數(shù)據(jù)覆蓋的情況。
如果每個(gè)子線程執(zhí)行完后能將發(fā)送郵件的信息返回給主線程,那么我們就可以在所有子線程結(jié)束后再存儲(chǔ)mail的信息了。
Java CallableRunnable任務(wù)不返回任何值,如果你希望在任務(wù)完成時(shí)能夠返回一個(gè)值,那么可以實(shí)現(xiàn)Callable接口而不是Runnable接口,Callable是一種具有類(lèi)型參數(shù)的泛型,它的類(lèi)型參數(shù)表示的是從方法call()中返回的值,并且必須使用ExecutorService.submit()方法調(diào)用它。
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()方法會(huì)產(chǎn)生Future對(duì)象,你可以用isDone()來(lái)查詢Future是否已經(jīng)完成,任務(wù)完成時(shí),可以用get()方法獲取任務(wù)的返回值,如果任務(wù)沒(méi)有完成,調(diào)用get()方法會(huì)阻塞主線程。
代碼實(shí)現(xiàn)在獲取返回結(jié)果時(shí),get()會(huì)阻塞主線程,為了使發(fā)送郵件的函數(shù)不被阻塞,我們需要新創(chuàng)建一個(gè)線程來(lái)運(yùn)行發(fā)送郵件的子線程。
類(lèi)Mailer為實(shí)現(xiàn)了Callable的發(fā)送郵件的具體實(shí)現(xiàn)的代碼。Mail為郵件的實(shí)體。
public class MailerTask extends Thread { private Mail mail;//郵件信息 private String sender;//發(fā)件人信息 //每個(gè)線程發(fā)送郵件的最大數(shù)量 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); // 去除重復(fù)的收件人 ListsendTos = Arrays.stream(mail.getSendTo().split(";")).distinct().collect(Collectors.toList()); // 存儲(chǔ)發(fā)送失敗的收件人 String sendTo = ""; // 存儲(chǔ)發(fā)送成功的收件人 String sended = ""; // 記錄發(fā)送郵件的次數(shù) int sendTimes = 0; Mailer.setSender(sender); List >> futures = new ArrayList<>(); // 每100個(gè)收件人創(chuàng)建一個(gè)線程用來(lái)發(fā)送郵件 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); } // 處理結(jié)果 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; } }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/67656.html
摘要:函數(shù)攜帶目的地址主題郵件體模板和一組關(guān)鍵字參數(shù)。許多擴(kuò)展操作是在假設(shè)有活動(dòng)的應(yīng)用程序和請(qǐng)求上下文的情況下進(jìn)行的。但是當(dāng)函數(shù)在一個(gè)不同的線程上執(zhí)行,應(yīng)用程序上下文需要人為地創(chuàng)建使用。例如,執(zhí)行函數(shù)可以將郵件發(fā)送到的任務(wù)隊(duì)列中。 許多類(lèi)型的應(yīng)用程序都會(huì)在某些事件發(fā)生的時(shí)候通知用戶,常用的溝通方法就是電子郵件。盡管在Flask應(yīng)用程序中,可以使用Python標(biāo)準(zhǔn)庫(kù)中的smtplib包來(lái)發(fā)送電...
摘要:網(wǎng)上也有不少人反饋用手機(jī)客戶端無(wú)法使用新浪郵箱發(fā)送郵件,隨后我嘗試用登錄新浪郵箱,也出現(xiàn)只能接收郵件而不能發(fā)送郵件的情況。三附錄錯(cuò)誤碼及建議解決方法發(fā)送郵件成功卻收不到郵件或收到郵件無(wú)主題無(wú)收件人亂碼新浪郵箱誠(chéng)信平臺(tái) 前言 ??JavaMail的使用本身并不難,網(wǎng)上有不少案例,簡(jiǎn)單易懂,而且有詳細(xì)的中文注解。但是由于JavaMail的機(jī)制設(shè)置不夠完善,特別是異常出錯(cuò)時(shí)的參考信息太少,給...
摘要:我拿網(wǎng)易郵箱賬號(hào)舉例子,那么我們?nèi)绾尾拍茏屇愕泥]箱賬號(hào)可以利用第三方發(fā)送郵件這里的第三方就是我們即將編寫(xiě)的程序。 一 前言 測(cè)試所使用的環(huán)境 測(cè)試使用的環(huán)境是企業(yè)主流的SSM 框架即 SpringMVC+Spring+Mybatis。為了節(jié)省時(shí)間,我直接使用的是我上次的SSM項(xiàng)目中整合Echarts開(kāi)發(fā)該項(xiàng)目已經(jīng)搭建完成的SSM環(huán)境。 標(biāo)題說(shuō)的四種姿勢(shì)指的是哪四種姿勢(shì)? 發(fā)送text...
閱讀 2611·2021-10-14 09:43
閱讀 3570·2021-10-13 09:39
閱讀 3304·2019-08-30 15:44
閱讀 3154·2019-08-29 16:37
閱讀 3718·2019-08-29 13:17
閱讀 2742·2019-08-26 13:57
閱讀 1834·2019-08-26 11:59
閱讀 1261·2019-08-26 11:46