ServerSocket 选项
SO_TIMEOUT:表示等待客户连接的超时时间。
SO_REUSEADDR:表示是否允许重用服务器所绑定的地址。
SO_RCVBUF:表示接收数据的缓冲区的大小。
我们先实现一个简单的服务器
package multithread1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class EchoServer {
private int port = 8000;
private ServerSocket serverSocket;
public EchoServer() throws IOException {
serverSocket = new ServerSocket(port);
System.out.println("服务器启动");
}
public void service() {
while (true) {
Socket socket = null;
try {
socket = serverSocket.accept();
Thread workThread = new Thread(new Handler(socket));
workThread.start();
} catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
public static void main(String args[]) throws IOException {
new EchoServer().service();
}
class Handler implements Runnable {
private Socket socket;
public Handler(Socket socket) {
this.socket = socket;
}
private PrintWriter getWriter(Socket socket) throws IOException {
OutputStream socketOut = socket.getOutputStream();
return new PrintWriter(socketOut, true);
}
private BufferedReader getReader(Socket socket) throws IOException {
InputStream socketIn = socket.getInputStream();
return new BufferedReader(new InputStreamReader(socketIn));
}
public String echo(String msg) {
return "echo:" + msg;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
System.out.println("New connection accepted "
+ socket.getInetAddress() + ":" + socket.getPort());
BufferedReader br = getReader(socket);
PrintWriter pw = getWriter(socket);
String msg = null;
while ((msg = br.readLine()) != null) {
System.out.println(msg);
pw.println(echo(msg));
if (msg.equals("bye"))
break;
}
} catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
}finally
{
try {
if (socket != null)
socket.close();
} catch (IOException e2) {
// TODO: handle exception
e2.printStackTrace();
}
}
}
}
}
多线程的例子
ThreadPoolTester
package multithread1;
public class ThreadPoolTester {
public static void main(String[] args) {
int num1 = 5;
int num2 = 3;
int numTasks = num1; //Integer.parseInt(args[0]);
int poolSize = num2; //Integer.parseInt(args[1]);
ThreadPool threadPool = new ThreadPool(poolSize);
for (int i = 0; i < numTasks; i++) {
threadPool.execute(createTask(i));
}
threadPool.join();
}
private static Runnable createTask(final int taskID) {
return new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("TASK " + taskID + ":start");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO: handle exception
System.out.println("Task " + taskID + ":end");
}
}
};
}
}
多线程服务器例子
线程池代码:
ThreadPool
package multithread1;
import java.util.LinkedList;
public class ThreadPool extends ThreadGroup{
private boolean isClosed = false; //线程池是否关闭
private LinkedList<Runnable> workQueue; //表示工作队列
private static int threadPoolID; //表示线程池ID
private int threadID; //表示工作线程ID
//poolSize 指定线程池中得工作线程数目
public ThreadPool(int poolSize) {
super("ThreadPool-" + (threadPoolID++));
// TODO Auto-generated constructor stub
setDaemon(true);
//创建工作队列
workQueue = new LinkedList<Runnable>();
for (int i = 0; i < poolSize; i++) {
new WorkThread().start(); //创建并启动工作线程
}
}
//向工作队列中加入一个新任务,由工作线程去执行该任务
public synchronized void execute(Runnable task) {
if (isClosed) {
//线程池被关闭则抛出IllegalStateException异常
throw new IllegalStateException();
}
if (task != null) {
workQueue.add(task);
//唤醒正在getTask()方法中等待任务的工作线程
notify();
}
}
//从工作队列中取出一个任务,工作线程会调用此方法
protected synchronized Runnable getTask()throws InterruptedException {
while (workQueue.size() == 0) {
if (isClosed) {
return null;
}
//如果工作队列中没有任务,就等待任务
wait();
}
return workQueue.removeFirst();
}
//关闭线程池
public synchronized void close() {
if (isClosed) {
isClosed = true;
//清空工作队列
workQueue.clear();
interrupt();
}
}
//等待工作线程把所有任务执行完
public void join() {
synchronized (this) {
isClosed = true;
notifyAll();//唤醒还在getTask()方法中等待任务额工作流程
}
Thread[] threads = new Thread[activeCount()];
//enumerate()方法继承自ThreadGroup类,获得线程组中当期所有活着的工作流程
int count = enumerate(threads);
//等待所有工作线程运行结束
for (int i = 0; i < count; i++) {
try {
threads[i].join();//等待工作线程运行结束
} catch (InterruptedException e) {
// TODO: handle exception
}
}
}
//内部类:工作线程
private class WorkThread extends Thread
{
public WorkThread () {
//加入到当前ThreadPool 线程组中
super(ThreadPool.this,"WorkThread-" + (threadID++));
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
while (!isInterrupted()) {
Runnable task = null;
try {
//取出任务
task = getTask();
} catch (InterruptedException e) {
// TODO: handle exception
}
//如果getTask()返回null或者线程执行getTask()时被中断,则结束此线程
if (task == null) {
return;
}
try {//运行任务,异常在catch 代码块中捕获
task.run();
} catch (Throwable e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
}
}
多线程服务器:
EchoServer
package multithread1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class EchoServer {
private int port = 8000;
private ServerSocket serverSocket;
private ThreadPool threadPool;
private final int POOL_SIZE = 4;
public EchoServer() throws IOException {
serverSocket = new ServerSocket(port);
/*
* 创建线程池
* Runtime 的availableProcessors()方法返回当前系统的CPU的数目
* 系统的CPU越多,线程池中的工作线程的数目也越多
* */
threadPool = new ThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE);
System.out.println("服务器启动");
}
public void service() {
while (true) {
Socket socket = null;
try {
socket = serverSocket.accept();
threadPool.execute(new Handler(socket));
} catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
public static void main(String args[]) throws IOException {
new EchoServer().service();
}
class Handler implements Runnable {
private Socket socket;
public Handler(Socket socket) {
this.socket = socket;
}
private PrintWriter getWriter(Socket socket) throws IOException {
OutputStream socketOut = socket.getOutputStream();
return new PrintWriter(socketOut, true);
}
private BufferedReader getReader(Socket socket) throws IOException {
InputStream socketIn = socket.getInputStream();
return new BufferedReader(new InputStreamReader(socketIn));
}
public String echo(String msg) {
return "echo:" + msg;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
System.out.println("New connection accepted "
+ socket.getInetAddress() + ":" + socket.getPort());
BufferedReader br = getReader(socket);
PrintWriter pw = getWriter(socket);
String msg = null;
while ((msg = br.readLine()) != null) {
System.out.println(msg);
pw.println(echo(msg));
if (msg.equals("bye"))
break;
}
} catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
}finally
{
try {
if (socket != null)
socket.close();
} catch (IOException e2) {
// TODO: handle exception
e2.printStackTrace();
}
}
}
}
}
使用JDK的线程池
java.util.concurrentpackage multithread1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class EchoServer {
private int port = 8000;
private ServerSocket serverSocket;
private ExecutorService executorService;
private final int POOL_SIZE = 4;
public EchoServer() throws IOException {
serverSocket = new ServerSocket(port);
/*
* 创建线程池
* Runtime 的availableProcessors()方法返回当前系统的CPU的数目
* 系统的CPU越多,线程池中的工作线程的数目也越多
* */
executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE);
System.out.println("服务器启动");
}
public void service() {
while (true) {
Socket socket = null;
try {
socket = serverSocket.accept();
executorService.execute(new Handler(socket));
} catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
public static void main(String args[]) throws IOException {
new EchoServer().service();
}
class Handler implements Runnable {
private Socket socket;
public Handler(Socket socket) {
this.socket = socket;
}
private PrintWriter getWriter(Socket socket) throws IOException {
OutputStream socketOut = socket.getOutputStream();
return new PrintWriter(socketOut, true);
}
private BufferedReader getReader(Socket socket) throws IOException {
InputStream socketIn = socket.getInputStream();
return new BufferedReader(new InputStreamReader(socketIn));
}
public String echo(String msg) {
return "echo:" + msg;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
System.out.println("New connection accepted "
+ socket.getInetAddress() + ":" + socket.getPort());
BufferedReader br = getReader(socket);
PrintWriter pw = getWriter(socket);
String msg = null;
while ((msg = br.readLine()) != null) {
System.out.println(msg);
pw.println(echo(msg));
if (msg.equals("bye"))
break;
}
} catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
}finally
{
try {
if (socket != null)
socket.close();
} catch (IOException e2) {
// TODO: handle exception
e2.printStackTrace();
}
}
}
}
}
防止死锁的代码。
package multithread1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
public class EchoServer {
private int port = 8000;
private ServerSocket serverSocket;
private ExecutorService executorService;
private final int POOL_SIZE = 4;
private int portForShutdown = 8001;
private ServerSocket serverSocketForShutdown;
private boolean isShutdown = false;
private Thread shutdownThread = new Thread() {
public synchronized void start() {
this.setDaemon(true);
super.start();
};
public void run() {
while (!isShutdown) {
Socket socketForShutdown = null;
try {
socketForShutdown = serverSocketForShutdown.accept();
BufferedReader br = new BufferedReader(
new InputStreamReader(
socketForShutdown.getInputStream()));
String command = br.readLine();
if (command.equals("shutdown")) {
long beginTime = System.currentTimeMillis();
socketForShutdown.getOutputStream().write(
"服务器正在关闭\r\n".getBytes());
isShutdown = true;
// 请求关闭线程池
// 线程池不再接收新的任务,但是会继续执行完工作队列中现有的任务
executorService.shutdown();
// 等待关闭线程池,每次等待的超时时间为30秒
while (!executorService.isTerminated()) {
executorService.awaitTermination(30,
TimeUnit.SECONDS);
}
serverSocket.close();
long endTime = System.currentTimeMillis();
socketForShutdown
.getOutputStream()
.write(("服务器已经关闭" + "用" + (endTime - beginTime) + "毫秒")
.getBytes());
socketForShutdown.close();
serverSocketForShutdown.close();
} else {
socketForShutdown.getOutputStream().write(
"错误的命令\r\n".getBytes());
socketForShutdown.close();
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
};
};
public EchoServer() throws IOException {
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(60000);
serverSocketForShutdown = new ServerSocket(portForShutdown);
/*
* 创建线程池 Runtime 的availableProcessors()方法返回当前系统的CPU的数目
* 系统的CPU越多,线程池中的工作线程的数目也越多
*/
executorService = Executors.newFixedThreadPool(Runtime.getRuntime()
.availableProcessors() * POOL_SIZE);
shutdownThread.start();
System.out.println("服务器启动");
}
public void service() {
while (!isShutdown) {
Socket socket = null;
try {
socket = serverSocket.accept();
socket.setSoTimeout(60000);
executorService.execute(new Handler(socket));
} catch (SocketTimeoutException e) {
// TODO: so exception
}catch (RejectedExecutionException e) {
// TODO: handle exception
try {
if (socket != null)
socket.close();
} catch (IOException e2) {}
return;
}catch (SocketException e) {
// TODO: handle exception
if (e.getMessage().indexOf("socket closed") != -1) return;
}
catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
public static void main(String args[]) throws IOException {
new EchoServer().service();
}
class Handler implements Runnable {
private Socket socket;
public Handler(Socket socket) {
this.socket = socket;
}
private PrintWriter getWriter(Socket socket) throws IOException {
OutputStream socketOut = socket.getOutputStream();
return new PrintWriter(socketOut, true);
}
private BufferedReader getReader(Socket socket) throws IOException {
InputStream socketIn = socket.getInputStream();
return new BufferedReader(new InputStreamReader(socketIn));
}
public String echo(String msg) {
return "echo:" + msg;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
System.out.println("New connection accepted "
+ socket.getInetAddress() + ":" + socket.getPort());
BufferedReader br = getReader(socket);
PrintWriter pw = getWriter(socket);
String msg = null;
while ((msg = br.readLine()) != null) {
System.out.println(msg);
pw.println(echo(msg));
if (msg.equals("bye"))
break;
}
} catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
} finally {
try {
if (socket != null)
socket.close();
} catch (IOException e2) {
// TODO: handle exception
e2.printStackTrace();
}
}
}
}
}