• 多任务处理:管理调度Executor 接口


    系统管理调度:Executor接口

     在上一节中我们已经看到,将客户服务器协议的细节封装起来(如EchoProtocol.java),就可以通过同一个协议实现来使用不同的"调度"方法(如,TCPEchoServerThread.javaTCPEchoServerThreadPool.java)。实际上,对于调度方法本身来说也是这样。Executor接口java.util.concurrent包的一部分)就代表了一个根据某种策略来执行Runnable实例的对象,其中可能包括了排队和调度的细节,或如何选择要执行的任务。Executor接口只定义了一个方法:

    interface Executor {

    void execute(Runnable task);

    }

    Java提供了大量的内置Executor接口实现,它们都可以简单方便地使用,也可以进行扩展性的配置。其中一些还提供了处理维护线程等繁琐细节的功能。例如,如果一个线程因为未捕获的异常或其他故障停止,它们就自动创建一个新的线程来替换原来的线程。 

    ExecutorService接口继承于Executor接口,并提供了一个更高级的工具来关闭服务器,包括正常的关闭和突然的关闭。ExecutorService还允许在完成任务后返回一个结果,这需要用到Callable接口,它和Runnable接口很像,只是多了一个返回值。

     我们可以通过调用Executors类的各种静态工厂方法来获取ExecutorService实例。示例程序TCPEchoServerExecutor.java演示了基本Executor工具的使用方法。

    TCPEchoServerExecutor.java

    0 import java.io.IOException;

    1 import java.net.ServerSocket;

    2 import java.net.Socket;

    3 import java.util.concurrent.Executor;

    4 import java.util.concurrent.Executors;

    5 import java.util.logging.Logger;

    6

    7 public class TCPEchoServerExecutor {

    8

    9 public static void main(String[] args) throws

    IOException {

    10

    11 if (args.length != 1) { // Test for correct # of args

    12 throw new IllegalArgumentException("Parameter(s):

    <Port>");

    13 }

    14

    15 int echoServPort = Integer.parseInt(args[0]); // Server

    port

    16

    17 // Create a server socket to accept client connection

    requests

    18 ServerSocket servSock = new

    ServerSocket(echoServPort);

    19

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

    21

    22 Executor service = Executors.newCachedThreadPool(); //

    Dispatch svc

    23

    24 // Run forever, accepting and spawning a thread for each

    connection

    25 while (true) {

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

    for connection

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

    28 }

    29 /* NOT REACHED */

    30 }

    31 }

    TCPEchoServerExecutor.java 

    1.设置:第11-20

    端口号是唯一的参数。与前面的例子一样,我们要创建ServerSocket实例和Logger例。这里它们不必声明为常量,因为我们不需要用匿名的Thread子类。

    2.获取一个Executor实例:第22

    Executors类的newCachedThreadPool()静态工厂方法创建了一个ExecutorService实例。在使用一个实现了Runnable接口的实例调用它的execute()方法时,如果必要它将创建一个新的线程来处理任务。然而,它首先会尝试使用已有的线程。如果一个线程空闲了60秒以上,则将移出线程池。这个策略几乎总是比前面两个TCPEchoServer*例子的效率高。

    3.反复循环,接收并执行连接:第25-28

    当一个新的连接请求到来时,将创建一个新的EchoProtocol实例并传递给serviceexecute()方法,该方法要么将其分配给一个已有的线程,要么创建一个新的线程来处理它。值得注意的是,当达到稳定状态时,缓存线程池服务最终将保持合适的线程数,以使每个线程都保持忙碌,同时又很少创建或销毁线程。

    只要有一个设计为使用Executor来调度客户端的服务器,我们就可以通过简单地改变Executor实例的类型来实现不同的调度策略。例如,如果我们想使用像TCPEchoServerPool.java中那样的固定大小的线程池,只需要改变与设置调度服务相关的一行代码:

    Executor service =Executors.newFixedThreadPool(threadPoolSize); 

    我们可以将线程池的大小设为1,转换成使用单一线程处理所有的客户端连接,或者使用以下方法来实现:

    Executor service = Executors.newSingleThreadExecutor();

    Executor方法中,如果一个"工人"线程由于某些故障死掉了,Executor将创建一个新的线程来代替它。而且,任务是在            Executor    的内部排队,而不是像我们最初的服务器那样在网络系统中排队。到现在为止,我们仅仅触及到了Java并发包的表层功能而已。

     

    相关下载:

    Java_TCPIP_Socket编程(doc)

    http://download.csdn.net/detail/undoner/4940239

     

    文献来源:

    UNDONER(小杰博客) :http://blog.csdn.net/undoner

    LSOFT.CN(琅软中国) :http://www.lsoft.cn

     

  • 相关阅读:
    LeetCode Reverse Nodes in k-Group
    LeetCode Unique Binary Search Trees II
    Binary Tree Zigzag Level Order Traversal
    JavaWeb--JSP
    Java--面向对象
    javaScript-进阶篇(三)
    javaScript-进阶篇(二)
    java--常用类
    javaScript-进阶篇(一)
    Java--数组
  • 原文地址:https://www.cnblogs.com/wuyida/p/6301068.html
Copyright © 2020-2023  润新知