服务器(多线程、线程池和缓冲队列)

来源:互联网 发布:txt转azw3软件 编辑:程序博客网 时间:2024/04/30 17:51

Server

package com.cloud.test4;import java.io.BufferedReader;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;import java.util.concurrent.BlockingQueue;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.TimeUnit;/** * 商业的服务器  * 1、多线程 thread  *      1)一个客户端启动一个线程为之服务  *      2)主线程监听客户端的请求  * 2、线程池 threadPool *      1)控制线程的数量,提升Server的伸缩性 *      2)减少线程创建的开销  * 3、缓冲队列 blockingQueue *      1)不要让客户端线程直接访问文件,数据库等资源  *      2)通过队列来做缓冲(客户端线程将数据放入队列中,让专门的线程负责将队列中的数据放入文件或者数据库中) *      3)队列必须可以是线程安全的,一般队列有阻塞的功能  * 4、封装好协议 */public class ServerDemo {private ServerSocket ss;private int online;// 连接的客户端数量private ExecutorService threadPool;// 线程池private BlockingQueue<String> queue;private String fileName;// 文件存储地址public ServerDemo() throws IOException {online = 0;fileName = "e:/file.txt";// 设置服务器端口ss = new ServerSocket(8899);// 创建指定线程数量的线程池threadPool = Executors.newFixedThreadPool(100);queue = new LinkedBlockingQueue<String>(1000);}public void start() throws IOException {SaveThread saveThread = new SaveThread();// 有未做完的任务,所以不设置成守护线程saveThread.start();// 连接线程 定时显示正在连接的客户端数量OnlineThread onlineThread = new OnlineThread();onlineThread.setDaemon(true);onlineThread.start();while (true) {// 等待接收客户端发送过来的请求Socket socket = ss.accept();// 实现了runnable接口的内部类Handler handler = new Handler(socket);// 线程池中的线程启动runnable中的run方法threadPool.execute(handler);}}// 实现runnable接口的类 因为线程已经创建 所以不再继承Thread类class Handler implements Runnable {private Socket socket;Handler(Socket socket) {this.socket = socket;}public void run() {try {incOnline();// 对话中获取输入输出流InputStream is = socket.getInputStream();// 听OutputStream os = socket.getOutputStream();// 说OutputStreamWriter osw = new OutputStreamWriter(os);PrintWriter pw = new PrintWriter(osw);InputStreamReader isr = new InputStreamReader(is);BufferedReader br = new BufferedReader(isr);// 先读取客户端发送过来的请求,再发送信息回去String line = br.readLine();boolean b = offer(line);if (b) {pw.print("ok");// 给客户端响应信号} else {pw.println("error");}// 自身封装缓冲,所以调用flush方法pw.flush();} catch (Exception e) {System.out.println("网络异常");} finally {if (socket != null)try {socket.close();decOnline();} catch (IOException e) {}}}}public synchronized void incOnline() {online++;}public synchronized void decOnline() {online--;}public synchronized int getOnline() {return online;}// 开启一个线程 记录当前与服务器连接的客户端数量private class OnlineThread extends Thread {public void run() {while (true) {try {System.out.println("online : " + getOnline());Thread.sleep(3000);} catch (InterruptedException e) {System.out.println("Interrupted");}}}}// 将字符串存入缓冲队列中private boolean offer(String str) {boolean b = false;try {b = queue.offer(str, 5, TimeUnit.SECONDS);} catch (InterruptedException e) {}return b;}// 取出缓冲队列中的字符串private String poll() {String line = null;try {line = queue.poll(1, TimeUnit.SECONDS);} catch (InterruptedException e) {}return line;}private class SaveThread extends Thread {@Overridepublic void run() {while (true) {try {Thread.sleep(2000);String line = null;FileOutputStream fos = new FileOutputStream(fileName, true);OutputStreamWriter osw = new OutputStreamWriter(fos);while ((line = poll()) != null) {osw.write(line);}osw.close();} catch (Exception e) {e.printStackTrace();}}}}public static void main(String[] args) throws Exception {System.out.println("server");ServerDemo sd = new ServerDemo();sd.start();}}

Client

package com.cloud.test4;import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.Socket;import java.util.Scanner;public class ClientDemo {public void request()throws Exception{//客户端 设置连接的服务器的位置Socket socket = new Socket("localhost",8899);//IP地址 端口号InputStream is = socket.getInputStream();//听OutputStream os = socket.getOutputStream();//说OutputStreamWriter osw = new OutputStreamWriter(os);PrintWriter pw = new PrintWriter(osw);InputStreamReader isr = new InputStreamReader(is);BufferedReader br = new BufferedReader(isr);//发送控制台中的信息Scanner scanner = new Scanner(System.in);String line = scanner.next();pw.println(line);pw.flush();//内部自带缓冲String str = br.readLine();if("ok".equals(str)){System.out.println("发送成功");}else{System.out.println("发送失败");}socket.close();}public static void main(String[] args)throws Exception {System.out.println("client");ClientDemo cd = new ClientDemo();cd.request();}}



原创粉丝点击