前段时间做了一个面向Socket编程的项目,现在有时间和大家分享一下
首先是线程池:
Java通过Executors提供四种线程池,分别为:
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
这里我用的是newCachedThreadPool,因为要满足多用户短连接的需求,newFixedThreadPool可能也是一种好的选择,因为它避免多次开启关闭线程造成的资源浪费,但考虑到当没用线程执行时,线程依然开启,浪费资源,就没有使用。newScheduledThreadPool和newSingleThreadExecutor不满足该项目需求。由于项目既需要接收数据又需要发送数据,就开启了两个Socket端口,而socket.accept()方法阻塞式的,在开启端口前就需要先通过 ExecutorService exc = Executors.newCachedThreadPool()方式创建线程池,在其中可以指定最大可创建线程数,默认值为1000.下面就是执行代码:
//获得当前正在执行的线程数
int count=((ThreadPoolExecutor)exec).getActiveCount();
//执行线程
exec.execute(new Task(client));
这里很重要的一点是Task这个类必须要实现Runnable接口,我这里面吧连接的通道传到Task中,然后通过socket.getInputStream()得到字节流,为了方便处理把它转化为字符流,new BufferedReader(new InputStreamReader(socket.getInputStream()));以及new PrintWriter(socket.getOutputStream(),true);
而且在实践过程发现重要一点,通道的一端发送数据后立刻关闭通道,在另一端依然可以接受到数据。特意写个测试代码给大家实践,包需要你们自己导入。
服务器端代码:
1 public class Server { 2 static ServerSocket server; 3 4 public static void main(String[] args) { 5 6 try { 7 server = new ServerSocket(8100); 8 while (true) { 9 Socket socket = server.accept(); 10 PrintWriter pw = new PrintWriter(socket.getOutputStream(), true); 11 pw.println("hi:客户端"); 12 pw.close(); 13 socket.close(); 14 System.out.println("服务器已经关闭"); 15 } 16 } catch (IOException e) { 17 18 e.printStackTrace(); 19 } 20 21 } 22 23 }
客户端代码:
public class Cilent {
public static void main(String[] args) {
try {
String s = "";
Socket socket = new Socket("localhost", 8100);
Thread.sleep(2000);
BufferedReader bf = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
if ((s = bf.readLine()) != null) {
System.out.println(s);
}
socket.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
研究后我想可能是因为
客户端 服务端
out-----x------->in
in<--------------out
=========================================================================================================
今天更到这里,后面会介绍一下如何利用osm数据画自己的地图,以及用java实现基于硬盘的TPR树。欢迎感兴趣的小伙伴一起讨论啊