说明
这是针对《Java并发编程实战》(Java Concurrency in Practice)一书中的示例代码进行扩展,并且进行验证的完整代码,具体背景可看这篇文章:1-《Java并发编程实战》(Java Concurrency in Practice) 代码示例
下面的示例代码都是针对书中的(不完整的)代码扩展,不再介绍具体上下文背景(如果你也在看这本书,可以拿我这里的示例代码做个参考,并欢迎提出意见和建议)
程序清单2-5
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
/**
* @DESCRIPTION:
* @USER: shg
* @DATE: 2024/1/13 11:15
*/
public class UnsafeCachingFactorizer extends HttpServlet {
private final AtomicReference<BigInteger> lastNumber = new AtomicReference<>();
private final AtomicReference<BigInteger[]> lastFactors = new AtomicReference<>();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
BigInteger i = extractFromRequest(req);
if (i.equals(lastNumber.get())) {
encodeIntoResponse(resp, i, lastFactors.get());
} else {
BigInteger[] factors = factor(i);
lastNumber.set(i);
lastFactors.set(factors);
encodeIntoResponse(resp, i, lastFactors.get());
}
}
private BigInteger extractFromRequest(HttpServletRequest req) {
return new BigInteger(req.getParameter("key"));
}
private void encodeIntoResponse(HttpServletResponse resp, BigInteger i, BigInteger[] factors) throws IOException {
System.out.println(i + "--->" + Arrays.asList(factors));
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.println("<html><body>");
writer.println("<h1>" + i + "因数分解结果为:" + Arrays.asList(factors));
writer.println("</body></html>");
}
private BigInteger[] factor(BigInteger number) {
List<BigInteger> factors = new ArrayList<>();
BigInteger divisor = BigInteger.valueOf(2);
while (number.compareTo(BigInteger.ONE) > 0) {
if (number.mod(divisor).equals(BigInteger.ZERO)) {
number = number.divide(divisor);
factors.add(divisor);
} else {
divisor = divisor.add(BigInteger.ONE);
}
}
return factors.toArray(new BigInteger[0]);
}
}
压测线程设置
使用Jmeter开启两个线程组,每个线程组传递的参数不一样,但是访问同一个Servlet组件(即:访问同一个UnsafeCachingFactorizer类),然后在控制台分析输出结果,具体操作如下图:
压测结果分析
首先要明确的是,这是一个Servlet组件(即:UnsafeCachingFactorizer类)的功能是因数分解,并且希望将最近的计算结果缓存起来,即当两个连续的请求对相同的数值进行因数分解时,可以直接使用上一次的计算结果,而无需重新计算。
并且我们可以事先知道是的129的因数分解结果应该是 3和43;24的因数分解结果应该是:2,2,2和3,现在看如下图: