java I/O 学习笔记2 ,线程池

来源:互联网 发布:怎么登陆淘宝卖家中心 编辑:程序博客网 时间:2024/05/02 00:06

线程池:就是为了解决一客户端一线程的过度资源消耗问题,而在预先定义好线程的数量,而当有新的请求接入时,就将这个新的请求接入封装成一个task丢到线程池中处理,在这种情况下,资源的使用是可控的。

同样,以一个客户端发送消息,服务器接收并且返回消息的例子作为分析。

思路:
Server端:
1. server端使用ServerSocket的一个实例,绑定端口并且监听,
2. 创建一个线程池,指定线程池属性
3. ServerSocket实例将接收到的每个socket单独封装成一个task,
4. 将task丢到线程池中处理
Client端:
1. 新建一个Socket实例,并且连接到server,(建议将这个Socket封装成一个单独的类),
2. 获取Socket的输入流和输出流,收发信息

Server端代码:三部分组成,ExecutorPoolServer.java,主函数入口
;ExecutePoolServerHandler.java,用于封装线程池的类;BIOSocketHandler.java;负责到客户端的Soket连接;

代码:
ExecutePoolServer.java

package learningNote.IO;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;public class ExecutePoolServer {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        int port=8090;        ServerSocket ss=new ServerSocket(port);        ExecutePoolServerHandler esph=new ExecutePoolServerHandler();//创建线程池        while(true){            System.out.println(esph.activtedThreadCount());//查看这个线程池上面的活跃线程数            Socket s=ss.accept();            esph.execute(new BIOSocketHandler(s));//将新的请求连接放入线程池中        }    }}

ExecutePoolServerHandler.java

package learningNote.IO;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ExecutorService;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class ExecutePoolServerHandler{    private ExecutorService es;    public ExecutePoolServerHandler() {        // TODO Auto-generated constructor stub        es=new ThreadPoolExecutor(1, 2, 1000, TimeUnit.MICROSECONDS, new ArrayBlockingQueue<Runnable>(10));//这个构造函数的说明可以查阅:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html#ThreadPoolExecutor(int, int, long, java.util.concurrent.TimeUnit, java.util.concurrent.BlockingQueue)    }    public void execute(Runnable task){        es.execute(task);//这里的参数必须是Runnable类型的实例,因为jvm创建的线程会根据此来调用run()方法    }    public int activtedThreadCount(){        return Thread.activeCount();    }}

BIOSocketHandler.java

package learningNote.IO;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.Socket;public class BIOSocketHandler implements Runnable{    private Socket s;    public BIOSocketHandler(Socket s) {        // TODO Auto-generated constructor stub        this.s = s;    }    @Override    public void run() {        // TODO Auto-generated method stub        try (BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream()));//获取socket的输入流             PrintWriter out=new PrintWriter(s.getOutputStream(),true);//获取socket的输出流,并且设置自动刷新缓冲区                ){            //读取输入消息并打印            String message=" ";            while(true){                //读取输入消息                while(true){                    String temp=in.readLine();                    if(temp.equals("ok")){                        break;                    }                    message+=temp+"\n";                }                //打印收到的消息                System.out.print(message);                //返回消息                String now=new java.util.Date().toString();                 out.println(now+" "+message+"ok");            }        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();            System.exit(1);        }    }}
  1. 当线程池中的线程(指定的最大线程)已经全部用完之后,新的task会被放到ArrayBlockingQueue,这时一个顺序队列,属于先进先出的一种能够算法.,就是最先进入的元素也会最先出队。
  2. 注意到server 端socket会一直存在直到client端的socket被关闭,也就是说,会导致线程的一直占用
  3. 注意InputStream中的read方法,这个方法本身也会引起阻塞因为它不会立即被返回直到:数据可用(input data is available ,),数据读取完毕(end of the file is detected ),或者抛出错误(throw a exception)。..前两者的情况不太清楚…因为这样岂不是会被返回两次??
  4. OutputStream中的write方法,也会造成阻塞,(这很大程度上与tcp/ip缓冲区以及网络状况有关)..

    Client端代码:
    ExecutePoolClient .java

package learningNote.IO;import java.io.IOException;import java.net.Socket;import java.net.UnknownHostException;public class ExecutePoolClient {    public static void main(String[] args) throws UnknownHostException, IOException {        // TODO Auto-generated method stub        Socket s=new Socket("127.0.0.1",8090);        new Thread(new BIOClientHandler(s)).start();    }}

BIOClientHandler.java

package learningNote.IO;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.Socket;public class BIOClientHandler implements Runnable {    private Socket s;    public BIOClientHandler(Socket s) {        // TODO Auto-generated constructor stub        this.s=s;    }    @Override    public void run() {        // TODO Auto-generated method stub        try(BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream()));            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));            PrintWriter out=new PrintWriter(s.getOutputStream(),true)){            while(true){                //从控制台读取输入                String message=" ";                  while(true){                      String temp=br.readLine();                      if(temp.equals("ok"))break;                      message+=temp+"\n";                  }                  //发送消息                  out.println(message+"ok");                  //读取消息                  String body=" ";                  while(true){                      String temp=in.readLine();                      if(temp.equals("ok"))break;                      body+=temp+"\n";                  }                  System.out.print(body);            }        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}
0 0
原创粉丝点击