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

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 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(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 {
		@Override
		public 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();
	}
}



你可能感兴趣的:(JavaSE核心Ⅱ)