- 浏览: 202983 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (67)
- 私人笔记 (43)
- 转载日志 (5)
- 学习笔记 (11)
- Java (8)
- Google Guice (1)
- ImageIo (2)
- mina (3)
- nio (1)
- epoll (1)
- ubuntu (2)
- dia (1)
- vysper (2)
- Guice (1)
- Jetty (1)
- Continuation (1)
- long polling (1)
- Bootstrap (1)
- lbs (1)
- Tomcat (1)
- JVM (1)
- GC (1)
- 图片处理 (2)
- 清除图片锯齿 (0)
- 业余折腾 (0)
- dpi (1)
- eclipse (1)
- Netty (3)
- android (1)
- javamail (1)
- Protobuf (1)
最新评论
-
sankby:
终于找到这个说明了,netty权威指南上关于readInter ...
Netty源码笔记I - 关于『注册SelectionKey#OP_ACCEPT』 -
liuchao150:
写个filter, 那struts2里的上传,File获取不到 ...
upload.parseRequest(request) 结果为null的一个恶心处理法 -
星璇凌:
这样改后,action中的set方法不起作用了,前台传到后台的 ...
upload.parseRequest(request) 结果为null的一个恶心处理法 -
l578682879:
于是,我自己实现一个servlet.Filter,并且把它的f ...
upload.parseRequest(request) 结果为null的一个恶心处理法 -
phperbar:
不错,效果还可以
用html5做了一个打气球小游戏
简要说明
1、基于javamail所做的批量发邮件小程序,SingleSender是普通发送,ThreadSender是多线程发送,MysqlSender是从数据库获取数据再调用ThreadSender来发送。
2、为啥写这个小程序呢?没啥特别的,只因最近想起thinking in java里面介绍的CountDownLatch类,为了练手多线程相关的技术而写了这个小程序,整个程序于我而言核心在ThreadSender里面的CountDownLatch。
3、jar依赖情况
1) 必须:activation.jar, mail.jar, commons-logging.jar, log4j-xx.jar, zTool-xx.jar(我写的另外一些小工具类,源码在 https://z-tool.googlecode.com/svn/trunk/zTool)
2) 可能需要:mysql-connector-java-xx.jar,velocity-xx-dep.jar
(注:上面版本号用xx代替了,依据实际情况找个合适的版本即可)
下面贴出SingleSender和ThreadSender的源码。详细源码在 https://github.com/auzll/zBatchSender
1、基于javamail所做的批量发邮件小程序,SingleSender是普通发送,ThreadSender是多线程发送,MysqlSender是从数据库获取数据再调用ThreadSender来发送。
2、为啥写这个小程序呢?没啥特别的,只因最近想起thinking in java里面介绍的CountDownLatch类,为了练手多线程相关的技术而写了这个小程序,整个程序于我而言核心在ThreadSender里面的CountDownLatch。
3、jar依赖情况
1) 必须:activation.jar, mail.jar, commons-logging.jar, log4j-xx.jar, zTool-xx.jar(我写的另外一些小工具类,源码在 https://z-tool.googlecode.com/svn/trunk/zTool)
2) 可能需要:mysql-connector-java-xx.jar,velocity-xx-dep.jar
(注:上面版本号用xx代替了,依据实际情况找个合适的版本即可)
下面贴出SingleSender和ThreadSender的源码。详细源码在 https://github.com/auzll/zBatchSender
public final class SingleSender extends AbstractSender { private static final Log LOG = LogFactory.getLog(SingleSender.class); /** * 发送一批邮件 * @param entities 邮件实体列表 */ public final List<MailEntity> send(List<MailEntity> entities) { int entitiesSize = null != entities ? entities.size() : 0; if (LOG.isInfoEnabled()) { LOG.info("method:send,entitiesSize:" + entitiesSize + ",senderParam:[" + this.toSimpleLog() + "]" + ",thread:" + Thread.currentThread().toString()); } if (entitiesSize < 1) { return entities; } /** TODO Test code begin */ // 模拟测试一下好了,不做实际发信 for (MailEntity entity : entities) { try { TimeUnit.SECONDS.sleep(new Random().nextInt(3)); } catch (InterruptedException e) { } if (LOG.isInfoEnabled()) { LOG.info("method:send,result:success,entity:[" + entity.toSimpleLog() + "],thread:" + Thread.currentThread().toString()); } } if (true) return entities; /** TODO Test code end */ Transport transport = null; Session session = null; int curTimes = 0; Properties sessionProperties = newProperties(); for (MailEntity entity : entities) { try { if (null == transport || !transport.isConnected() || curTimes == transportUsingTimes) { if (null != transport && transport.isConnected()) { transport.close(); } session = Session.getInstance(sessionProperties); transport = session.getTransport(new URLName("smtp", smtpHost, smtpPort, null, from.getAddress(), password)); // 获取新的transport curTimes = 0; transport.connect(); if (LOG.isDebugEnabled()) { LOG.debug("method:send,desc:transport connect,thread:" + Thread.currentThread().toString()); } } MimeMessage message = new MimeMessage(session); if (null != from) { message.setFrom(from); } if (null != entity.getTo()) { message.addRecipient(RecipientType.TO, entity.getTo()); } if (null != entity.getCcTo()) { message.addRecipient(RecipientType.CC, entity.getCcTo()); } if (null != entity.getBccTo()) { message.addRecipient(RecipientType.BCC, entity.getBccTo()); } if (null != subject) { message.setSubject(subject); } if (null != entity.getContent()) { message.setText(entity.getContent(), charset); } else if (null != content) { message.setText(content, charset); } // 发送邮件 transport.sendMessage(message, message.getAllRecipients()); // 成功发送 entity.setSuccess(true); if (LOG.isInfoEnabled()) { LOG.info("method:send,result:success,entity:[" + entity.toSimpleLog() + "],thread:" + Thread.currentThread().toString()); } } catch (Exception e) { // 发送失败 entity.setSuccess(false); if (LOG.isDebugEnabled()) { LOG.debug("method:send,result:fail,entity:[" + entity.toSimpleLog() + "],thread:" + Thread.currentThread().toString(), e); } else { LOG.info("method:send,result:fail,entity:[" + entity.toSimpleLog() + "],thread:" + Thread.currentThread().toString() + ",e:" + e.getMessage()); } } finally { curTimes++; } } if (null != transport && transport.isConnected()) { try { transport.close(); } catch (Exception e) { LOG.info("method:send,desc:close transport,thread:" + Thread.currentThread().toString() , e); } } return entities; } /** * 发送一封邮件 * @param entity 邮件实体 */ public final MailEntity send(MailEntity entity) { List<MailEntity> entities = new ArrayList<MailEntity>(); entities.add(entity); send(entities); return entity; } private Properties newProperties() { String address = from.getAddress(); String host = address; int atIndex = address.indexOf('@'); if (-1 != atIndex) { host = address.substring(atIndex + 1); } Properties props = new Properties(); props.put("mail.smtp.localhost", host); props.put("mail.from", address); props.put("mail.debug", mailDebug); if (null != password) { props.put("mail.smtp.auth", true); } return props; } }
public final class ThreadSender extends AbstractSender { private static final Log LOG = LogFactory.getLog(ThreadSender.class); private class Worker implements Runnable { private CountDownLatch latch; private List<MailEntity> entities; public Worker(CountDownLatch latch, List<MailEntity> entities) { this.latch = latch; this.entities = entities; } public void run() { new SingleSender() .charset(charset) .smtpHost(smtpHost) .smtpPort(smtpPort) .transportUsingTimes(transportUsingTimes) .from(from) .password(password) .subject(subject) .content(content) .send(entities); if (LOG.isDebugEnabled()) { LOG.debug("method:Worker$run,desc:latch count down,thread:" + Thread.currentThread().toString()); } latch.countDown(); } } /** 默认的最大线程数量:Runtime.getRuntime().availableProcessors() * 2 */ public static final int DEFAULT_THREAD_SIZE = Runtime.getRuntime().availableProcessors() * 2; /** 每个线程单次任务默认的发送邮件量 */ public static final int DEFAULT_TASK_OF_EACH_THREAD = 10; /** 线程数量 */ private int threadSize = DEFAULT_THREAD_SIZE; /** 每个线程单次任务最大发送邮件量 */ private int taskOfEachThread = DEFAULT_TASK_OF_EACH_THREAD; private ExecutorService executorService; /** 是否在发送邮件后关闭executorService,若executorService由外界传入就不关闭,否则关闭 */ private boolean shutdownExecutor = false; public ThreadSender() { this(Executors.newCachedThreadPool()); this.shutdownExecutor = true; } public ThreadSender(ExecutorService executorService) { this.executorService = executorService; } /** * 发送一批邮件 * @param entities 邮件实体列表 */ public final List<MailEntity> send(List<MailEntity> entities) { int entitiesSize = null != entities ? entities.size() : 0; if (LOG.isInfoEnabled()) { LOG.info("method:send,entitiesSize:" + entitiesSize + ",thread:" + Thread.currentThread().toString()); } if (entitiesSize < 1) { return entities; } int maxTask = threadSize * taskOfEachThread; if (entities.size() > maxTask) { throw new BatchSendException("Too much task, max is " + maxTask + ", current is " + entities.size()); } int i = 0, toIndex = 0, len = entities.size(); int count = len / taskOfEachThread; if (len % taskOfEachThread > 0) { count++; } CountDownLatch latch = new CountDownLatch(count); int realCount = 0; while (i < len) { if (LOG.isDebugEnabled()) { LOG.debug("method:send,desc:split task,taskIndex:" + realCount); } toIndex = i + taskOfEachThread; if (toIndex > len) { toIndex = len; } executorService.execute(new Worker(latch, entities.subList(i, toIndex))); i = toIndex; realCount++; } if (count != realCount) { throw new BatchSendException("Unexpected error[count != realCount], count is " + count + ", realCount is " + realCount); } try { if (LOG.isDebugEnabled()) { LOG.debug("method:send,desc:begin await,thread:" + Thread.currentThread().toString()); } latch.await(); if (LOG.isDebugEnabled()) { LOG.debug("method:send,desc:finish await,thread:" + Thread.currentThread().toString()); } } catch (InterruptedException e) { throw new BatchSendException(e); } if (shutdownExecutor) { if (LOG.isDebugEnabled()) { LOG.debug("method:send,desc:try shutdown executorService,thread:" + Thread.currentThread().toString()); } executorService.shutdownNow(); } return entities; } public ThreadSender taskOfEachThread(int taskOfEachThread) { this.taskOfEachThread = taskOfEachThread; return this; } public ThreadSender threadSize(int threadSize) { this.threadSize = threadSize; return this; } }
发表评论
-
还是在csdn写博客吧!
2018-06-16 23:43 418博客,还是要尽量写写的。 最早是javaeye(iteye) ... -
准备继续写博客,放在github pages
2018-01-11 15:58 57很久不写博客,年终回忆总结时,像是工作学习断了层,太多有价值的 ... -
[简略记录]使用Netty过程遇到的一个傻X错误——异常处理
2014-07-31 23:20 6104最近基于netty写了点服务器端的程序,算是第一次比较正式的使 ... -
入职五周年
2014-07-13 11:56 2998简单的记一记吧。 今天是我正式入职五周年的日子!2009年大 ... -
初试python des
2013-11-08 13:38 960初试python des,使用了pyDes: from ... -
再整理一段javamail的发信代码
2013-10-15 15:26 746Properties p = new Pro ... -
我遇到tomcat 7 full gc频繁的问题
2013-07-11 22:45 8045近日开始关注JVM的问题,先用jstat -gcut ... -
【练习代码】试用百度BAE和练手jetty continuation的副成品 —— 一个简陋的WEB版LBS聊天应用
2013-07-04 22:49 1436最近写了个测试小应 ... -
【练习代码】写了基于java nio的RepeatServer -- by auzll
2013-05-21 11:53 1681昨天在翻看mina源码时,突然想起我貌似还 ... -
【源码学习】Mina笔记 (一)
2013-05-21 00:36 1527因最近准备 ... -
试玩github pages
2013-05-09 23:55 1022哈哈,试玩了一下github pages,还 ... -
试试html5的拖拉事件和FileReader
2013-05-09 15:59 1864<html> <head> ... -
java格式化GMT时间
2013-05-09 12:54 1205FastDateFormat.getInstance(&quo ... -
maven 若干学习笔记
2012-12-27 12:50 8641、从项目路径设置dependency <depen ... -
REST 相关资源
2012-12-26 10:00 947REST 论文的中文版:http://www.redsaga. ... -
我的常用链接
2012-10-17 10:27 926The Java EE 6 Tutorial: http:// ... -
JAVA用ImageIO处理JPG图片
2012-10-15 15:36 1797Image srcImage = ImageIO.re ... -
用java试试在Mysql环境中注入sql
2012-10-09 08:06 1219一般的说,在java环境中,使用java.sql.St ... -
ant打包之排除特定文件
2012-06-20 19:38 4371<copy todir="${build.di ... -
[BUG排查日记]2012-06-04
2012-06-04 20:57 996最近更新系统,在 ...
相关推荐
本文将详细介绍如何利用MyBatis结合多线程和CountDownLatch闭锁来实现数据的批量插入。 首先,我们来看`mybatis批处理`。MyBatis的批处理功能允许我们在一次数据库连接中执行多条SQL语句,从而减少了数据库连接的...
在Java多线程编程中,CountDownLatch是一个非常重要的同步工具类,它可以帮助我们协调多个线程之间的交互。本文将深入探讨CountDownLatch的工作原理、使用场景以及相关源码分析。 CountDownLatch是一个计数器,初始...
如何使用CountDownLatch同步java多线程 CountDownLatch 是 Java 并发编程中的一种常用工具,用于控制多个线程的并发执行。它可以实现多个线程之间的同步操作,使得线程之间可以协调工作,避免了线程之间的互相干扰...
`CountDownLatch` 是一个计数器,可以用于协调多个线程间的活动,等待所有线程完成各自的任务后,主线程或其他线程才能继续执行。 首先,让我们深入理解 `CountDownLatch` 的工作原理。`CountDownLatch` 在构造时会...
Java 使用 CountDownLatch 等待多线程全部执行完成 CountDownLatch 是 Java 中的...CountDownLatch 是 Java 中一个非常强大且灵活的同步工具类,使用它可以轻松地实现多线程的同步操作,提高程序的执行效率和可靠性。
这个小程序的主要目的是通过分割大文件并同时从服务器下载多个部分,来提高文件下载速度。下面将详细介绍多线程下载器的设计和实现原理,以及如何利用Java进行编程。 首先,我们需要理解多线程的概念。在Java中,...
JAVA多线程CountDownLatch使用详解 JAVA多线程CountDownLatch是JAVA多线程编程中的一种同步工具,主要用来让某个线程等待其他线程执行完毕后再继续执行。下面我们将详细介绍JAVA多线程CountDownLatch的使用和原理。...
这个“多线程终极案例程序”旨在帮助Java开发者深化对多线程的理解,通过一个具体的“多兵种联合攻击防御塔”游戏案例来实践。下面将详细解释该案例中的关键知识点。 首先,多线程是并发执行多个任务的能力,可以...
"CountDownLatch" 和 "Thread" 是Java编程语言中实现多线程并行执行的关键工具,它们有助于提高程序的运行效率和响应速度。 **多线程并行执行** 多线程并行执行是指在同一个程序中同时运行多个线程,每个线程负责...
- 使用`Platform.runLater()`方法,可以确保在JavaFX的应用程序线程(也称为事件调度线程)中执行UI相关的更新,防止出现线程安全问题。 2. **音乐播放多线程**: - Java提供了`javax.sound.sampled`包来处理音频...
在编程领域,多线程是实现并发执行任务的关键技术,特别是在服务器端开发和高并发应用中,多线程能够充分利用CPU资源,提高程序的运行效率。这个名为"多线程demo程序-轻松掌握多线程技术"的项目,旨在帮助开发者理解...
- **CountDownLatch**:允许一个线程等待其他线程完成操作,常用于多线程并发测试。 - **CyclicBarrier**:允许多个线程等待直到达到某个屏障点再一起继续执行。 - **Semaphore**:信号量,控制同时访问特定资源...
标题提到的“多线程执行完后主程序再执行(包括需要子线程返回结果)”是一个典型的多线程同步问题。在这个场景中,主程序会启动多个子线程去执行不同的任务,然后等待所有子线程执行完毕,最后处理子线程返回的结果...
1. **多线程基础**:论文可能会首先介绍多线程的基本概念,解释为什么在JAVA中需要使用多线程,以及多线程如何提升程序的执行效率。这部分内容可能会涉及到线程的创建、启动、同步和通信等基础知识。 2. **JAVA多...
Java中CountDownLatch进行多线程同步详解及实例代码 CountDownLatch是Java中的一种多线程同步...CountDownLatch是一种非常有用的多线程同步辅助类,通过它可以轻松地同步多个任务的执行,从而提高程序的效率和可靠性。
- `CyclicBarrier`和`CountDownLatch`:用于线程同步,协调多个线程同时开始或结束操作。 了解并熟练掌握这些知识点,你就能在实际开发中灵活运用Java的多线程特性,编写出高效、稳定的并发程序。通过实践和不断...
在Java编程中,多线程是一项关键技能,它能让程序同时执行多个任务,提升系统效率。本项目"多线程demo/java多线程练习"旨在通过实际操作来深入理解和掌握多线程技术,同时模拟数据库操作,这在现代应用程序开发中至...
Java多线程允许程序同时执行多个独立的代码段,这在处理大数据、网络通信、用户界面更新等场景中尤其有用。书中详细介绍了Java多线程的核心概念,如线程的创建、启动、同步、协作以及生命周期管理。读者将学习如何...
在编程领域,多线程是实现并发执行任务的重要机制,特别是在现代计算机系统中,它能够充分利用多核处理器的计算能力,提高程序的运行效率。本文将深入探讨如何在实际编程中实现多线程,以及如何管理和监控线程状态,...
Java多线程与并发编程是Java开发中至关重要的一部分,它涉及到如何高效地利用CPU资源,以实现程序的并行执行。在操作系统层面,多任务和多进程是通过分配不同的内存空间来实现的,而线程则共享同一进程的内存,这...