想了解下Java线程池的用法,恰好最近要做一个简易的邮件通知中间功能,所以写下这个笔记。见笑。
servlet代码SendEmailServlet.java:
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 发送邮件servlet
* @author gandalf
*
*/
public class SendEmailServlet extends HttpServlet{
private static final int corePoolSize = 1; // 线程池中所保存的核心线程数。
private static final int maximumPoolSize = 4; //线程池允许创建的最大线程数。
private static final long keepAliveTime = 0; //当前线程池线程总数大于核心线程数时,终止多余的空闲线程的时间。
//邮件队列(线程共享)
private static BlockingQueue<Runnable> emailQueue = new LinkedBlockingDeque<Runnable>();
//实例化线程池(线程共享)
private static ThreadPoolExecutor threadPool= new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, emailQueue,new ThreadPoolExecutor.AbortPolicy());
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//要发送的内容
String content = req.getParameter("msg");
//打印当前活动线程和队列大小
System.out.println("--当前线程池大小【"+ threadPool.getPoolSize() + "】,当前队列大小【"+emailQueue.size()+"】");
//加入队列
threadPool.execute(new SendThread(content));
//返回结果
PrintWriter out = resp.getWriter();
out.println("over");
}
@Override
public void destroy() {
//关闭线程池
threadPool.shutdown();
super.destroy();
}
}
package servlet;
/**
* 发送邮件线程
* @author gandalf
*
*/
public class SendThread implements Runnable{
private String content;
public SendThread (String content){
this.content = content;
}
@Override
public void run() {
try {
//发送邮件。。。。
Thread.sleep(1000);
System.out.println("sendMail:"+content);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
web.xml配置:
<servlet>
<servlet-name>sendMsg</servlet-name>
<servlet-class>servlet.SendEmailServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sendMsg</servlet-name>
<url-pattern>/sendMsg.do</url-pattern>
</servlet-mapping>
测试类,通过GET方式,向127.0.0.1/projectName/sendMsg.do发送请求:
package test;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class ThreadPoolTest1 {
public static void main(String[] args) {
for(int i=0; i< 20; i++){
new MyThread(i+"-t1").run();
new MyThread(i+"-t2").run();
new MyThread(i+"-t3").run();
new MyThread(i+"-t4").run();
}
}
}
class MyThread implements Runnable{
private String name;
public MyThread(String name){
this.name = name;
}
@Override
public void run() {
try {
Thread.sleep(500);
System.out.println(name+"-----");
URL getUrl = new URL("http://127.0.0.1/ThreadPool/sendMsg.do?msg=sendemailNO:"+name);
HttpURLConnection connection = (HttpURLConnection) getUrl
.openConnection();
// 进行连接,但是实际上get request要在下一句的connection.getInputStream()函数中才会真正发到服务器
connection.connect();
// 取得输入流,并使用Reader读取
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),"utf-8"));//设置编码,否则中文乱码
String lines;
while ((lines = reader.readLine()) != null){
System.out.println(lines);
}
reader.close();
// 断开连接
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
测试结果:
--当前线程池大小【0】,当前队列大小【0】
--当前线程池大小【1】,当前队列大小【0】
sendMail:sendemailNO:0-t1
--当前线程池大小【1】,当前队列大小【0】
--当前线程池大小【1】,当前队列大小【1】
sendMail:sendemailNO:0-t2
--当前线程池大小【1】,当前队列大小【1】
--当前线程池大小【1】,当前队列大小【2】
sendMail:sendemailNO:0-t3
--当前线程池大小【1】,当前队列大小【2】
--当前线程池大小【1】,当前队列大小【3】
sendMail:sendemailNO:0-t4
--当前线程池大小【1】,当前队列大小【3】
--当前线程池大小【1】,当前队列大小【4】
sendMail:sendemailNO:1-t1
--当前线程池大小【1】,当前队列大小【4】
--当前线程池大小【1】,当前队列大小【5】
sendMail:sendemailNO:1-t2
--当前线程池大小【1】,当前队列大小【5】
--当前线程池大小【1】,当前队列大小【6】
sendMail:sendemailNO:1-t3
--当前线程池大小【1】,当前队列大小【6】
--当前线程池大小【1】,当前队列大小【7】
sendMail:sendemailNO:1-t4
--当前线程池大小【1】,当前队列大小【7】
--当前线程池大小【1】,当前队列大小【8】
sendMail:sendemailNO:2-t1
sendMail:sendemailNO:2-t2
sendMail:sendemailNO:2-t3