成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

java mail 多線程處理大量收件人,并將發(fā)送結(jié)果儲(chǔ)存到數(shù)據(jù)庫(kù)

jsummer / 1022人閱讀

摘要:郵件信息發(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 Callable

Runnable任務(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ù)的收件人
        List sendTos = 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

相關(guān)文章

  • Flask Web Development —— Email

    摘要:函數(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ā)送電...

    SKYZACK 評(píng)論0 收藏0
  • JavaMail郵件發(fā)送不成功的那些坑人情況及分析說(shuō)明

    摘要:網(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í)的參考信息太少,給...

    y1chuan 評(píng)論0 收藏0
  • 結(jié)合Spring發(fā)送郵件的四種正確姿勢(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...

    doodlewind 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<