Java Socket 4

第四章 进阶

1、多线程

1)继承Thread类,复写run()方法,实例化。(只适用于没有继承其他类时)

2)实现Runnable接口,实现run(),把实例化的对象传递给Thread构造函数

启动 start()

2Logger 写日志,线程安全,可以在并行运行的不同线程中调用它的方法。

Logger.getLogger()静态工厂方法可获取一个Logger实例,同名字的Logger是同一个实例。

并发服务器的两种方法

1、            一客户一线程

为每个连接都创建一个新的线程来处理

while (true) {

                     Socket clntSock = servSock.accept(); // Block waiting for connection

                     // Spawn thread to handle new connection

                     Thread thread = new Thread(new EchoProtocol(clntSock, logger));

                     thread.start();

                     logger.info("Created and started Thread " + thread.getName());

}

EchoProtocol实现了Runnable接口)

2、            线程池

每个线程都会消耗资源,限制总线程数,并重复使用。

在服务器启动时,创建固定数量的线程池。

具体来说:服务器创建一个ServerSocket实例,再创建N个线程,每个线程反复循环,从共享的ServerSocket实例接受客户端连接(这里demo用的匿名内部类),当多线程都调用同一个ServerSocket实例的accept()方式时,它们都阻塞等待,知道新的一个连接成功建立。

行为上类似:一组迭代服务器。

              // Create a server socket to accept client connection requests

              final ServerSocket servSock = new ServerSocket(echoServPort);

              final Logger logger = Logger.getLogger("practical");   

       // Spawn a fixed number of threads to service clients

              for (int i = 0; i < threadPoolSize; i++) {

                     Thread thread = new Thread() {

                            public void run() {

                                   while (true) {

                                          try {

                                                 // Wait for a connection

                                                 Socket clntSock = servSock.accept();

                                                 // Handle it 这里是静态方法

                                                 EchoProtocol.handleEchoClient(clntSock, logger);      

                                          } catch (IOException ex) {

                                                 logger.log(Level.WARNING, "Client accept failed",

                                                               ex);

                                          }

                                   }

                            }

                     };

                     thread.start();

                     logger.info("Created and started Thread = " + thread.getName());

              }

     线程池的调度:

线程池的大小最好能根据负载情况进行调整,在系统负载增加时扩展线程池大小,Java的调度工具:Executor接口。

Executor接口:代表了一个根据某种策略来执行Runnable实例的对象,其中可能包含了排队、调度的细节,或如何选择要执行的任务。通常使用 Executor 而不是显式地创建线程。需实现execute()方法。

       ExecutorService 接口继承于Executor接口,并提供了更高级的工具来关闭服务器。

      Executors类的各种静态工厂方法,获取 ExecutorService 实例。

              // Create a server socket to accept client connection requests

              ServerSocket servSock = new ServerSocket(echoServPort);

 

              Logger logger = Logger.getLogger("practical");

 

              Executor service = Executors.newCachedThreadPool(); // Dispatch svc

 

              // Run forever, accepting and spawning threads to service each

              // connection

              while (true) {

                     Socket clntSock = servSock.accept(); // Block waiting for connection

                     service.execute(new EchoProtocol(clntSock, logger));

              }

execute()方法:要么将其分配给一个已有的线程,要么创建一个新线程。

修改调度策略:使用Executors类的不同的静态工厂方法,比如:

固定大小线程池:newFixedThreadPool(int nThreads)

单一线程池:newSingleThreadExecutor()

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值