一.ThreadPoolTaskExecutor创建方式
1.注入线程池对象五个参数,面试常问
<bean id="taskExcetor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="10" />
<property name="keepAliveSeconds" value="200" />
<property name="maxPoolSize" value="20" />
<property name="queueCapacity" value="20" />
<property name="rejectedExecutionHandler">
<bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
</property>
</bean>
属性字段说明
corePoolSize:线程池维护线程的最少数量
keepAliveSeconds:允许的空闲时间
maxPoolSize:线程池维护线程的最大数量
queueCapacity:缓存队列
rejectedExecutionHandler:对拒绝task的处理策略
2.execute方法执行过程
如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maxPoolSize,建新的线程来处理被添加的任务。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maxPoolSize,那么通过handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
当线程池中的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。
3.代码中调用线程池,异步处理日志
@Autowired
private ThreadPoolTaskExecutor taskExcetor;
@GetMapping("test")
public void test(){
taskExcetor.execute(new Runnable() {
@Override
public void run() {
RobotVoiceInfoEntity robotVoiceInfo = new RobotVoiceInfoEntity();
robotVoiceInfo.setCreateTime(new Date());
robotVoiceInfo.setInset(inset);
robotVoiceInfo.setRobotName(robotName);
robotVoiceInfo.setText(text);
robotVoiceInfoService.save(robotVoiceInfo);
}
});
}
二.Executors创建线程池
1.创建线程池
@Component
public class SocketServer {
public static Map<String, Socket> map = new ConcurrentHashMap<String, Socket>();
@PostConstruct
public void acceptData() {
new Thread(new Runnable() {
@Override
public void run() {
ExecutorService pool = Executors.newFixedThreadPool(50);
try(ServerSocket serverSocket = new ServerSocket(Integer.parseInt(port))) {
while(true) {
Socket socket = serverSocket.accept();
String ip = socket.getInetAddress().toString();
map.put(ip,socket);
Callable<Void> task = new SocketCallable(socket,ip);
pool.submit(task);
}
}catch(BindException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
2.socket多线程等待客户端链接
private Logger logger = LoggerFactory.getLogger(this.getClass());
private Socket socket;
private String ip;
public SocketCallable(Socket socket,String ip) {
this.socket = socket;
this.ip = ip;
}
@Override
public Void call() {
try {
InputStream inputStream = socket.getInputStream();
DataInputStream dis = new DataInputStream(inputStream);
OutputStream outputStream = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(outputStream);
while(true) {
byte[] datas1 = new byte[7];
dis.readFully(datas1);
String prefix = Hex2AscUtil.hex2Asc(datas1.length, datas1);
String hex = prefix.substring(12);
byte[] datas2 = null;
if("80".equals(hex)) {
datas2 = new byte[8];
dis.readFully(datas2);
byte[] reqdata = {(byte) 0x57, 0x4b, 0x4c, 0x59, 0x09, 0x00, (byte) 0x80, 0x00, 0x00};
dos.write(reqdata);
dos.flush();
String resp = Hex2AscUtil.hex2Asc(reqdata.length, reqdata);
}else{
logger.info("socket解析数据不正确");
continue;
}
}
}catch(Exception e) {
e.printStackTrace();
}finally {
if(socket != null)
try {
Socket remove = SocketServer.map.remove(ip);
socket.close();
}catch(IOException e1) {
e1.printStackTrace();
}
}
return null;
}
}