网站设计器,建设银行纪检监察网站,格子铺网站建设方案,青岛百度整站优化服务目录
一、线程池
1. 构建线程池的类
2. 创建任务
3. 执行任务
测试
二、URL编码
解决方案
测试
三、如何接收客户端发送的全部信息
解决方案
测试
四、作业
1. 了解工厂模式
2. 了解反射技术 一、线程池
昨天使用了数据库连接池#xff0c;我们了解了连接池的优…目录
一、线程池
1. 构建线程池的类
2. 创建任务
3. 执行任务
测试
二、URL编码
解决方案
测试
三、如何接收客户端发送的全部信息
解决方案
测试
四、作业
1. 了解工厂模式
2. 了解反射技术 一、线程池
昨天使用了数据库连接池我们了解了连接池的优点那么也可以使用线程池来管理线程
java自带的线程池的参数有 核心线程数最大线程数线程活跃时间时间单位任务队列线程工厂拒绝策略
为了学习了解线程池我们先手写一个简单的线程池只需要做到核心线程可重复利用就行
1. 构建线程池的类
属性核心线程数任务队列
方法获取线程静态代码块执行任务需要的参数线程任务 Runnable
为了避免创建多个对象还需要设置单例模式 package com.shao.net;import java.util.concurrent.LinkedBlockingQueue;public class ThreadPool {// 定义一个成员静态变量存储单例对象private static ThreadPool instance;// 线程池核心线程数private final static int MAX_THREAD_NUM 10;// 存放任务的队列private static final LinkedBlockingQueueRunnable taskQueue new LinkedBlockingQueue();static {for (int i 0; i MAX_THREAD_NUM; i) {final int finalI i;new Thread(new Runnable() {Overridepublic void run() {/*** 线程池的线程从队列中取出任务这时线程不在临界区了自动释放锁然后执行任务当执行完任务后* 因为是while循环所以会在 synchronized (taskQueue) 等待* 当锁释放后并且当前线程被唤醒时会尝试获取锁* 如果获取到锁会进入临界区如果队列中有任务则取出然后执行任务如果没有则等待* 等待下次获取到锁会继续从上次进入等待态的位置继续往下执行也就是 taskQueue.wait() 开始往下执行* */while (true) {Runnable task null;synchronized (taskQueue) {System.out.println(线程 finalI 准备完成);// 队列为空等待while (taskQueue.isEmpty()) {try {taskQueue.wait(); // 使当前线程等待释放锁} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(线程 finalI 开始执行);// 从队列中取出任务task taskQueue.poll();}if (task ! null) {// 执行任务task.run();}}}}).start();}}// 私有化构造函数private ThreadPool() {}// 获取对象public static ThreadPool getInstance() {synchronized (ThreadPool.class) {if (instance null) {instance new ThreadPool();}return instance;}}public void execute(Runnable task) {// 当方法被调用时会尝试获取锁如果获取到锁则将任务加入队列并唤醒等待的线程synchronized (taskQueue) {taskQueue.add(task);taskQueue.notify();}}
}2. 创建任务
这里的任务是之前线程执行的代码我们把需要线程执行的任务放到一个类里然后实现Runnable package com.shao.net;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;public class MyTask implements Runnable {private InputStream is;private OutputStream os;public MyTask(InputStream is, OutputStream os) {this.is is;this.os os;}Overridepublic void run() {// 定义一个字节数组存放客户端发送的请求信息byte[] bytes new byte[1024];// 读取客户端发送的数据返回读取的字节数int len 0;try {len is.read(bytes);if (len -1) {return;}// 将读取的字节数组转换为字符串String msg new String(bytes, 0, len);// 调用HttpRequest类解析请求信息HttpRequest httpRequest new HttpRequest(msg);// 拼接请求的静态资源的路径// 路径是相对路径从模块的根路径开始String filePath webs/ httpRequest.getRequestModule();HttpResponse httpResponse new HttpResponse(os, httpRequest);// 响应数据httpResponse.response(filePath);} catch (IOException e) {e.printStackTrace();}}
}3. 执行任务
初始化线程池来一个用户连接时就创建一个任务然后交给线程池线程池取出一条线程执行任务的 run 方法
package com.shao.net;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;public class Tomcat {// 初始化线程池ThreadPool threadPool ThreadPool.getInstance();public Tomcat() {ServerSocket ss null;try {ss new ServerSocket(8080);while (true) {// 调用accept()方法阻塞等待直到有客户端连接到服务器返回一个Socket对象用于与该客户端通信Socket socket ss.accept();System.out.println(客户端连接成功);// 获取Socket对象的输入流用于读取客户端发送的数据InputStream is socket.getInputStream();// 获取Socket对象的输出流用于向客户端发送数据OutputStream os socket.getOutputStream();// 创建一个任务对象将输入输出流作为参数传过去MyTask myTask new MyTask(is, os);// 把任务作为参数传递给ThreadPool的execute()方法启动一个线程执行MyTask对象中的run()方法threadPool.execute(myTask);}} catch (IOException e) {e.printStackTrace();} finally {//关闭连接通道try {ss.close();} catch (IOException e) {e.printStackTrace();}}}
}测试 二、URL编码
在HTTP请求中如果参数包含中文字符会进行URL编码以避免乱码或传输错误。URL编码是一种将URL中的非ASCII字符如中文字符转换为可以在Web浏览器和服务器之间传输的格式的过程。
URL编码会将非ASCII字符转换为十六进制编码以便于在HTTP请求中安全传输。
URL编码的基本原理 URL编码将非ASCII字符如中文字符转换为%后跟两位十六进制数字的形式。例如空格在URL编码中通常被转换为%20。对于中文字符它们会被转码为以%E开头后面跟着若干位十六进制数字的字符串。 解决方案
在接收到请求信息后先进行解码然后再解析信息
URLDecoder.decode(需要解码的字符串, 字符集或编码方式) 在 MyTask 类中添加 测试 三、如何接收客户端发送的全部信息
目前我们的 Tomcat 最多只能一次接收 1KB因为定义的字节数组只有1024个字节 但是如果客户端发送的请求参数非常非常多呢超过了 1024 个字节了怎么办
把字节数组定义的大一点不行的因为网络传输一次最多传输 8KB超过 8KB 就会分批传输接收参数时也需要分批接收
那怎么判断参数已经接收完
参数有很多一般是使用POST方法而POST方法的请求头有 Content-Length 的字段表示请求体的总长度
我们来试一下打印一下请求的参数信息
这里可以看到 Content-Length 的值是 26表示请求体的参数长度为26字节图中显示参数的长度为 25因为解析后没有显示参数连接符 我们来使用 Apipost 来压力测试一下参数很多是什么样子 可以看到只读取到了一部分 出师表 的内容而且还有乱码这是因为没有完整读取一个 汉字的字节UTF-8 编码中一个汉字需要 3 个字节 解决方案
package com.shao.net;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;public class MyTask implements Runnable {private InputStream is;private OutputStream os;private int totalLength;private StringBuilder sb;public MyTask(InputStream is, OutputStream os) {this.is is;this.os os;}Overridepublic void run() {// 定义一个字节数组存放客户端发送的请求信息byte[] bytes new byte[1024];// 读取客户端发送的数据返回读取的字节数int len 0;try {// 第一次读取请求信息len is.read(bytes);if (len -1) {return;}// 将读取的字节数组转换为字符串String msg new String(bytes, 0, len);// 调用HttpRequest类解析请求信息HttpRequest httpRequest new HttpRequest(msg);/** 如果已读取的数据长度等于请求体的总长度并且请求方法是 POST说明请求体可能还没有读取完需要读取剩余的数据* */if (bytes.length len POST.equals(httpRequest.getRequestMethod())) {// 创建一个StringBuilder对象用于拼接请求信息sb new StringBuilder();sb.append(msg);// 获取 POST 请求方法中的请求体的总长度String length httpRequest.getRequestHeaderParams().get(Content-Length);if (length ! null) {totalLength Integer.parseInt(length);}// 调用方法读取剩余的请求体数据msg getNotReadMsg(httpRequest, bytes, msg);}// 把请求信息进行URL解码然后根据 UTF-8 进行编码String decodedMsg URLDecoder.decode(msg, utf-8);// 调用HttpRequest类解析请求信息httpRequest new HttpRequest(decodedMsg);// 拼接请求的静态资源的路径// 路径是相对路径从模块的根路径开始String filePath webs/ httpRequest.getRequestModule();HttpResponse httpResponse new HttpResponse(os, httpRequest);// 响应数据httpResponse.response(filePath);} catch (IOException e) {e.printStackTrace();}}/*** 读取剩余的请求体数据*/private String getNotReadMsg(HttpRequest httpRequest, byte[] bytes, String msg) throws IOException {int len;// 获取请求的参数HashMapString, String requestBodyParams httpRequest.getRequestBodyParams();// 请求参数的数量int size requestBodyParams.size();// 计算第一次读取到的请求体中参数的长度SetMap.EntryString, String entries requestBodyParams.entrySet();int partLength 0;for (Map.EntryString, String entry : entries) {partLength (entry.getKey() entry.getValue()).length();}// 减去第一次读取到的请求体中参数的长度如果存在多个参数需要考虑到 的个数if (size 1) {totalLength - (partLength (size - 1));} else {totalLength - partLength;}// 判断是否还有数据没有读完while (totalLength 0) {// 第二次读取请求信息len is.read(bytes);// 如果读取的字节数大于0表示读取到数据了if (len 0) {// 将读取的字节数组转换为字符串msg new String(bytes, 0, len);// 拼接字符串sb.append(msg);// 减去读取的字节数totalLength - len;} else {break;}}// 转成字符串格式返回return sb.toString();}
}测试
可以看出已经全部读取到了第二个参数也读取到了 四、作业
1. 了解工厂模式
优化 Dao现在在 Service 层调用Dao层都要 new 一下这样就比较占内存比如调用的都是 UserDao那么只需要创建一次 UserDao 的对象就行了
2. 了解反射技术
优化 Servlet 通过配置文件可以动态的创建 Servlet 对象 文章转载自: http://www.morning.kpcjl.cn.gov.cn.kpcjl.cn http://www.morning.rqmqr.cn.gov.cn.rqmqr.cn http://www.morning.cwwts.cn.gov.cn.cwwts.cn http://www.morning.zcqtr.cn.gov.cn.zcqtr.cn http://www.morning.rzbgn.cn.gov.cn.rzbgn.cn http://www.morning.drbd.cn.gov.cn.drbd.cn http://www.morning.clwhf.cn.gov.cn.clwhf.cn http://www.morning.jcxgr.cn.gov.cn.jcxgr.cn http://www.morning.dansj.com.gov.cn.dansj.com http://www.morning.rbkl.cn.gov.cn.rbkl.cn http://www.morning.pctsq.cn.gov.cn.pctsq.cn http://www.morning.pprxs.cn.gov.cn.pprxs.cn http://www.morning.wlqbr.cn.gov.cn.wlqbr.cn http://www.morning.addai.cn.gov.cn.addai.cn http://www.morning.zcfmb.cn.gov.cn.zcfmb.cn http://www.morning.cznsq.cn.gov.cn.cznsq.cn http://www.morning.hdnd.cn.gov.cn.hdnd.cn http://www.morning.zlnkq.cn.gov.cn.zlnkq.cn http://www.morning.lhhkp.cn.gov.cn.lhhkp.cn http://www.morning.iknty.cn.gov.cn.iknty.cn http://www.morning.lcbt.cn.gov.cn.lcbt.cn http://www.morning.qlwfz.cn.gov.cn.qlwfz.cn http://www.morning.qdsmile.cn.gov.cn.qdsmile.cn http://www.morning.xrrjb.cn.gov.cn.xrrjb.cn http://www.morning.ljbpk.cn.gov.cn.ljbpk.cn http://www.morning.fznj.cn.gov.cn.fznj.cn http://www.morning.hkng.cn.gov.cn.hkng.cn http://www.morning.bxgpy.cn.gov.cn.bxgpy.cn http://www.morning.dpbdq.cn.gov.cn.dpbdq.cn http://www.morning.rlqqy.cn.gov.cn.rlqqy.cn http://www.morning.tfznk.cn.gov.cn.tfznk.cn http://www.morning.yrsg.cn.gov.cn.yrsg.cn http://www.morning.ymjrg.cn.gov.cn.ymjrg.cn http://www.morning.gpfuxiu.cn.gov.cn.gpfuxiu.cn http://www.morning.hqmfn.cn.gov.cn.hqmfn.cn http://www.morning.lhptg.cn.gov.cn.lhptg.cn http://www.morning.tbqbd.cn.gov.cn.tbqbd.cn http://www.morning.qrwdg.cn.gov.cn.qrwdg.cn http://www.morning.rkwwy.cn.gov.cn.rkwwy.cn http://www.morning.qqnjr.cn.gov.cn.qqnjr.cn http://www.morning.nwcgj.cn.gov.cn.nwcgj.cn http://www.morning.langlaitech.cn.gov.cn.langlaitech.cn http://www.morning.grtwn.cn.gov.cn.grtwn.cn http://www.morning.gczzm.cn.gov.cn.gczzm.cn http://www.morning.fnssm.cn.gov.cn.fnssm.cn http://www.morning.lhygbh.com.gov.cn.lhygbh.com http://www.morning.qfdyt.cn.gov.cn.qfdyt.cn http://www.morning.prmbn.cn.gov.cn.prmbn.cn http://www.morning.nyqxy.cn.gov.cn.nyqxy.cn http://www.morning.ghkgl.cn.gov.cn.ghkgl.cn http://www.morning.zttjs.cn.gov.cn.zttjs.cn http://www.morning.pluimers.cn.gov.cn.pluimers.cn http://www.morning.tkzqw.cn.gov.cn.tkzqw.cn http://www.morning.wnwjf.cn.gov.cn.wnwjf.cn http://www.morning.nqwz.cn.gov.cn.nqwz.cn http://www.morning.pwmm.cn.gov.cn.pwmm.cn http://www.morning.twdkt.cn.gov.cn.twdkt.cn http://www.morning.byrlg.cn.gov.cn.byrlg.cn http://www.morning.dwgcx.cn.gov.cn.dwgcx.cn http://www.morning.brxzt.cn.gov.cn.brxzt.cn http://www.morning.tqpds.cn.gov.cn.tqpds.cn http://www.morning.mnyzz.cn.gov.cn.mnyzz.cn http://www.morning.mnlk.cn.gov.cn.mnlk.cn http://www.morning.mzmqg.cn.gov.cn.mzmqg.cn http://www.morning.zrbpx.cn.gov.cn.zrbpx.cn http://www.morning.zxfr.cn.gov.cn.zxfr.cn http://www.morning.yzygj.cn.gov.cn.yzygj.cn http://www.morning.krdmn.cn.gov.cn.krdmn.cn http://www.morning.bgnkl.cn.gov.cn.bgnkl.cn http://www.morning.nhpmn.cn.gov.cn.nhpmn.cn http://www.morning.dqpnd.cn.gov.cn.dqpnd.cn http://www.morning.bkgfp.cn.gov.cn.bkgfp.cn http://www.morning.qcmhs.cn.gov.cn.qcmhs.cn http://www.morning.huayaosteel.cn.gov.cn.huayaosteel.cn http://www.morning.ypxyl.cn.gov.cn.ypxyl.cn http://www.morning.wbfg.cn.gov.cn.wbfg.cn http://www.morning.ghwtn.cn.gov.cn.ghwtn.cn http://www.morning.qhkx.cn.gov.cn.qhkx.cn http://www.morning.qmncj.cn.gov.cn.qmncj.cn http://www.morning.zwdrz.cn.gov.cn.zwdrz.cn