Java多线程
进程与线程
Java线程
线程状态的切换
同步与锁
生产者与消费者模型
锁与死锁
多线程-条件变量Condition
前言
多线程能应用在那些场景?
例如:消息通信场景
一、场景设计
以下内容思路来自于 Netty权威指南(第二版) 2.1.2节中的TimeServer1.服务端
- 服务端创建ServerSocket监听设置的端口
- Server.accpet()阻塞等待socket请求
- 接收到请求,创建一个处理线程进行socket通信
2.处理线程
- 创建socket的输入流InputStream->in
- 创建socket的输出流PrintWriter-> out
- 处理socket的输入流
- 响应socket连接,写入输出流
- 没有继续写入时退出线程
3.客户端
- 调用服务端ip:端口创建socket连接
- 创建输出流PrintWrite -> out(注意客户端的输出流就是服务端的输入流)
- 创建输入流InputStream -> in(注意客户端的输入流就是服务端的输出流)
- 写输出流
- 处理服务端的输入流
- 结束客户端进程
二、示例代码
1.服务端
public class TimeServer {
public static void main(String[] args) throws IOException {
int port = 8080;
if(args != null && args.length > 0){
try {
port = Integer.valueOf(args[0]);
}catch (Exception e){
}
}
ServerSocket server = null;
try {
//监听端口
server = new ServerSocket(port);
Socket socket = null;
while (true){
//一直等待
socket = server.accept();
new Thread(new TimeServerHandler(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(server != null){
server.close();
server = null;
}
}
}
}
2.客户端
public class TimeClient {
public static void main(String[] args) {
int port = 8080;
if(args != null && args.length > 0){
try {
port = Integer.valueOf(args[0]);
}catch (Exception e){
}
}
Socket socket = null;
BufferedReader in = null;
PrintWriter out = null;
try {
socket = new Socket("127.0.0.1",port);
//客户端的输入,服务端的输出
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//客户端的输出,服务端的输入
out = new PrintWriter(socket.getOutputStream(),true);
out.println("QUERY TIME ORDER");
String resp = in.readLine();
System.out.println("服务端输出:"+resp);
}catch (Exception e){
}finally {
if(in != null){
try{
in.close();
}catch (IOException e){
}finally {
in = null;
}
}
if(out != null){
out.close();
out = null;
}
if(socket != null){
try{
socket.close();
}catch (IOException e){
}
socket = null;
}
}
}
}
3.服务端处理线程
public class TimeServerHandler implements Runnable{
private Socket socket;
TimeServerHandler(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try{
in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
out = new PrintWriter(this.socket.getOutputStream(),true);
String currentTime = null;
String body = null;
System.out.println("socket连接");
while(true){
body = in.readLine();
System.out.println(body);
if(body == null){
break;
}
System.out.println("The time server recevier order :" + body);
currentTime ="QUERY TIME ORDER".equalsIgnoreCase(body)?new java.util.Date(System.currentTimeMillis()).toString():"BAD ORDER";
out.println(currentTime);
}
}catch (Exception e){
}finally {
if(in != null){
try{
in.close();
}catch (IOException e){
}finally {
in = null;
}
}
if(out != null){
out.close();
out = null;
}
if(this.socket != null){
try{
this.socket.close();
}catch (IOException e){
}
this.socket = null;
}
}
}
}
三、服务端伪异步处理-线程池
在服务端通过线程池进行线程的控制,避免重复创建线程,代码如下
服务端:
public class TimeServerAsyn {
public static void main(String[] args) throws IOException {
int port = 8080;
if(args != null && args.length > 0){
try {
port = Integer.valueOf(args[0]);
}catch (Exception e){
}
}
ServerSocket server = null;
try {
//服务端监听端口
server = new ServerSocket(port);
System.out.println("端口:" + port + "监听成功");
Socket socket = null;
//创建线程池处理客户端请求
TimeServerHandlerExecutePool singleExcutor = new TimeServerHandlerExecutePool(50,10000);
while (true){
socket = server.accept();
//有一个socket请求就往线程池里面塞
singleExcutor.execute(new TimeServerHandler(socket));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(server != null){
server.close();
server = null;
}
}
}
}
线程池代码:
public class TimeServerHandlerExecutePool {
private ExecutorService executor;
public TimeServerHandlerExecutePool(int maxPoolSize,int queueSize){
executor = new ThreadPoolExecutor(
Runtime.getRuntime().availableProcessors(),
maxPoolSize,
120L,
TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(queueSize));
}
public void execute(Runnable runnable){
executor.execute(runnable);
}
}
总结
相关参考书籍:
<<Netty权威指南(第二版)>>