java - new Thread().start内部类的使用场景?
阿神
阿神 2017-04-18 09:19:21
0
4
1563

下面的这个方法是发邮件的抽象出来的一个公用方法:

String[] to 表示收件人列表;
subject  邮件主题;
templateName 邮件末班,用velocity写的,
Map params 参数,用来填充velocity中的某些字段取值的
public void sendHtmlWithTemplate(String[] to, String subject, String templateName, Map<String, Object> params) {
    final MimeMessage mimeMessage = mailSender.createMimeMessage();
    try {
        final MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage);
        messageHelper.setFrom(simpleMailMessage.getFrom());
        if (ENV_ONLINE.equals(environment)) {
            messageHelper.setTo(to);
            messageHelper.setSubject(subject);
        } else {
            messageHelper.setTo(adminEmail);
            messageHelper.setSubject(subject + Arrays.asList(to));
        }
        messageHelper.setSentDate(new Date());
        final String content = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, templateName, "UTF-8",
                                                                           params);
        final String[] logTo = to;
        messageHelper.setText(content, true);
        new Thread() {

            @Override
            public void run() {
                mailSender.send(mimeMessage);
                logger.error("Mailsentto: " + Arrays.asList(logTo) + "\nContent: " + content);
            }
        }.start();
    } catch (Exception e) {
        logger.error("emailServiceError error:" + e.getMessage(), e);
    }
}

在上面的发邮件的代码中,使用了内部类如下:

new Thread() {
    @Override
    public void run() {
        mailSender.send(mimeMessage);
        logger.error("Mailsentto: " + Arrays.asList(logTo) + "\nContent: " + content);
    }
}.start();

我觉得在这个地方做这个控制是很恰当的吧,为什么team leader让我删掉这个new Thread()的部分。
原话:“把new Thread全部删掉,这些邮件发送不了的bug都没有暴露出来; 邮件发送模块的代码采用异步发送方式,失去异常事务回滚的能力,new Thread要全部删除;” 不懂是什么意思啊?

问题:
1.为什么要去掉new Thread()?
2.在什么样的并发业务场景下,需要使用new Thread()这样的方式?有没有更好的解决方法?
3.在并发场景下,使用new Thread().start()的方式有什么弊端?每次new Thread新建对象性能会很差么?邮件服务也是当触发某个业务规则的时候,可能需要大量发送一下邮件,用线程池好不好呢?

阿神
阿神

闭关修行中......

membalas semua(4)
伊谢尔伦

@Youming telah pun menyebut aspek menyusahkan kelas dalaman tanpa nama. Biar saya terangkan berdasarkan perniagaan anda:

  1. Mengikut logik kod sedia ada, kaedah sendHtmlWithTemplate yang perkhidmatan e-mel kami harus dedahkan kepada dunia luar haruslah kaedah mailSender.send, bukan sendHtmlWithTemplate, jadi tidak perlu mendedahkan semula kaedah

    yang kami dedahkan kepada dunia luar Mulakan urutan untuk menghantar e-mel secara tidak segerak, kerana bagi pemanggil, anda sebenarnya perlu memberitahu sama ada menghantar e-mel itu berjaya kali ini, dan jika ia gagal/pengecualian berlaku, apakah adalah punca kegagalan itu. Jika anda mengikuti rancangan anda yang sedia ada, dunia luar mungkin merasakan bahawa tidak kira sama ada e-mel dihantar berjaya atau gagal, dunia luar tidak akan melihatnya, yang bermaksud bahawa e-mel itu tidak dapat diteruskan dan akan dicuba semula selepas beberapa ketika . Jadi menghantar e-mel secara tidak segerak harus diserahkan kepada pemanggil anda, bukan dalam kaedah anda
  2. Dengan mengandaikan bahawa penghantaran e-mel kami mungkin merupakan tindakan yang memakan masa, jika kami memulakan urutan untuk setiap e-mel yang masuk, ini bermakna terdapat banyak urutan dalam sistem. Ini bermakna bahawa akan terdapat banyak penukaran benang, dan penukaran benang akan menyebabkan penyekatan dan bangun Semua ini melibatkan penukaran mod pengguna dan mod kernel atau penukaran konteks benang, yang sangat intensif CPU dan melampau. Dalam kes ini, jika urutan sistem tidak terkumpul, keseluruhan perkhidmatan akan TURUN dan perkhidmatan akan berada dalam keadaan tidak tersedia. new Thread() sememangnya operasi yang sangat mahal
  3. Jika anda ingin menghantar e-mel secara tidak segerak dengan betul, anda benar-benar perlu melakukannya dalam kumpulan benang
  4. Cara yang lebih baik ialah menghantar mesej e-mel melalui MQ (pertimbangkan masalah biasa yang menyakitkan mesej: 1. Adakah mesej itu akan hilang? 2. Apa yang perlu dilakukan jika mesej itu dihantar semula), dan biarkan ia pelayan berasingan Pelayan yang menghantar mel melakukannya. Cara lain ialah dengan menyimpannya dalam jadual pangkalan data terlebih dahulu Jika keperluan ketepatan masa tidak begitu tinggi, kemudian mulakan pemasa dan hantarnya perlahan-lahan.
小葫芦

Objek tanpa nama sangat mudah, tetapi objek tanpa nama juga syaitan Jika ia tidak digunakan dengan betul, aplikasi anda akan runtuh. Ambil contoh anda sebagai contoh Jika anda tidak mengawal parameter menghantar e-mel, contohnya, jika anda terus menunggu selepas tamat masa berlaku semasa penghantaran, maka urutan ini akan menjadi hantu yang sunyi. Lepaskan, adakah ini yang harus dilakukan oleh pengaturcara?
Jika anda bertanya mengapa kepala anda meminta anda mengalih keluar tempat ini, saya hanya boleh mengatakan bahawa dia tidak cukup mempercayai keupayaan anda, jadi dia tidak berani untuk membiarkan anda mengawal syaitan ini.
Awak tanya senario apa yang sesuai, saya cuma boleh katakan tiada senario yang sesuai, hanya orang yang berkebolehan.

黄舟

Jika anda ingin menghantar sejumlah besar e-mel, anda boleh membuat baris gilir Jika terdapat terlalu banyak utas, ia mungkin tidak bagus.

Peter_Zhu

Maaf, saya baru nampak masalahnya sekarang.

Untuk butiran, sila rujuk kepada jawapan @iMouseWu dan @有明.

Jika anda pernah menulis js, anda boleh memahami bahawa new Thread() di sini adalah bersamaan dengan permintaan ajax, yang merupakan tingkah laku tak segerak Sebelum tugasan urutan selesai, kaedah itu telah kembali kepada pemanggil (dan tiada Pengecualian yang disebabkan oleh menghantar e-mel akan dibuang), itulah yang dikatakan oleh ketua anda "Pepijat yang tidak boleh menghantar e-mel ini belum didedahkan" .

Jika anda menganggap jumlah konkurensi adalah besar, anda boleh menggunakan redis+kafka (atau komponen mesej lain) untuk memberitahu perkhidmatan e-mel untuk menghantar e-mel dalam bentuk mesej.

Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan