Java 具有单线程执行器的RESTful web服务的体系结构?

Java 具有单线程执行器的RESTful web服务的体系结构?,java,web-services,rest,lifecycle,executor,Java,Web Services,Rest,Lifecycle,Executor,我想知道对于带有单线程执行器的RESTful web服务,什么样的体系结构可能是最好的 我的目标是: 调用RESTful web服务 web服务在线程队列中添加一个任务,并每1次执行所有任务1 实例化对象的生命周期非常重要(必须只有一个线程队列)。我知道RESTful web服务生命周期是“每个请求”(我认为类似于@RequestScoped),因此我看到了两个选项: 备选案文1: public class RestService { protected final static Exe

我想知道对于带有单线程执行器的RESTful web服务,什么样的体系结构可能是最好的

我的目标是:

  • 调用RESTful web服务
  • web服务在线程队列中添加一个任务,并每1次执行所有任务1
  • 实例化对象的生命周期非常重要(必须只有一个线程队列)。我知道RESTful web服务生命周期是“每个请求”(我认为类似于@RequestScoped),因此我看到了两个选项:

    备选案文1:

    public class RestService {
        protected final static Executor executor;
        protected final static Implementation1 impl1;
        protected final static Implementation2 impl2;
    
        static {
            executor = Executors.newSingleThreadExecutor();
            impl1 = new Implementation1();
            impl2 = new Implementation2();
        }
    }
    
    @Path("/servicename")
    public class MyService extends RestService {
        @POST
        @Path("/compute")
        public void compute(){
            executor.execute(new Runnable(){
                public void run(){
                    impl1.compute();
                }
            });
        }
    }
    
    备选案文2:

    @Singleton
    public class RestService {
        private Executor executor;
        private Implementation1 impl1;
        private Implementation2 impl2;
    
        public RestService () {
            executor = Executors.newSingleThreadExecutor();
            impl1 = new Implementation1();
            impl2 = new Implementation2();
        }
    
        public void execute(Runnable run){
            executor.execute(run);
        }
    
        public Implementation1 getImplementation1(){
            return impl1;
        }
    
        public Implementation2 getImplementation2(){
            return impl2;
        }
    
    }
    
    @Path("/servicename")
    public class MyService {
    
        @Inject
        private RestService rs;
    
        @POST
        @Path("/compute")
        public void compute(){
            rs.execute(new Runnable(){
                public void run(){
                    rs.getImplementation1().compute();
                }
            });
        }
    } 
    
    对于选项1,我不确定静态字段的“生命周期”。我应该使用哪个选项?你会怎么做

    谢谢

    编辑: 选项3(由EJB容器处理的线程)和“排序”并不重要:

    @Singleton
    public class RestService {
        private final Executor executor;
        private final Implementation1 impl1;
        private final Implementation2 impl2;
    
        public RestService () {
            executor = Executors.newSingleThreadExecutor();
            impl1 = new Implementation1();
            impl2 = new Implementation2();
        }
    
        public void compute1(){
            executor.execute(new Runnable(){
                public void run(){
                    impl1.compute();
                }
            });
        }
    
        public void compute2(){
            executor.execute(new Runnable(){
                public void run(){
                    impl2.compute();
                }
            });
        }
    
    }
    
    @Path("/servicename")
    public class MyService {
    
        @Inject
        private RestService rs;
    
        @POST
        @Path("/compute1")
        public void compute1(){
            rs.compute1();
        }
    
        @POST
        @Path("/compute2")
        public void compute2(){
            rs.compute2();
        }
    } 
    

    我认为选项3仍然比选项1和2好。

    我认为这样做是个坏主意。线程应该由容器处理,而不是由代码处理

    如果要在JavaEE应用服务器上部署,应该让它处理线程

    如果要在非阻塞I/O服务器(如Netty或vert.x)上部署,则应该让它处理线程

    在任何情况下都不应该管理线程

    静态字段在.class加载时实例化。它们不像实例那样具有“生命周期”。在类装入器删除.class文件之前,它们不会被清理


    如果必须有这种行为,我会使用JMS队列来排序处理,或者使用生产者/消费者deque来管理它。您希望处理是异步的。让REST服务将令牌或回执返回给客户机,并让他们回来查看处理何时完成。如果队伍很长,你就无法知道他们的衬衫什么时候准备好了。收据让他们回来检查结果是否有效。

    我认为这样做不好。线程应该由容器处理,而不是由代码处理

    如果要在JavaEE应用服务器上部署,应该让它处理线程

    如果要在非阻塞I/O服务器(如Netty或vert.x)上部署,则应该让它处理线程

    在任何情况下都不应该管理线程

    静态字段在.class加载时实例化。它们不像实例那样具有“生命周期”。在类装入器删除.class文件之前,它们不会被清理


    如果必须有这种行为,我会使用JMS队列来排序处理,或者使用生产者/消费者deque来管理它。您希望处理是异步的。让REST服务将令牌或回执返回给客户机,并让他们回来查看处理何时完成。如果队伍很长,你就无法知道他们的衬衫什么时候准备好了。收据允许他们回来检查结果是否可用。

    如果您使用Spring,然后将业务逻辑分离为单独的组件(bean)将这些bean注入到服务类中,只需更改业务逻辑bean的“scope”属性,就可以有效地控制实现的线程模型

    这是一个例子

    这种方法可以让您轻松地修改/试验解决方案,并发现适合您情况的最佳替代方案


    就架构而言,我建议您将系统分层(松耦合、高内聚、关注点分离等)。在这方面,您可能至少有一个服务层(REST)、一个业务层和一个数据层(dao)。各层通过接口相互作用。使用Spring将事物连接在一起(注入依赖项)。这使您能够灵活地注入不同的实现。例如,为您的业务类注入模拟DAO以进行单元测试。REST服务所在的服务层将执行请求/响应的转换、一些验证、确定要调用的业务组件并调用它们

    如果使用Spring,然后将业务逻辑分离为单独的组件(bean),并将这些bean注入到服务类中,那么只需更改业务逻辑bean的“scope”属性,就可以有效地控制实现的线程模型

    这是一个例子

    这种方法可以让您轻松地修改/试验解决方案,并发现适合您情况的最佳替代方案


    就架构而言,我建议您将系统分层(松耦合、高内聚、关注点分离等)。在这方面,您可能至少有一个服务层(REST)、一个业务层和一个数据层(dao)。各层通过接口相互作用。使用Spring将事物连接在一起(注入依赖项)。这使您能够灵活地注入不同的实现。例如,为您的业务类注入模拟DAO以进行单元测试。REST服务所在的服务层将执行请求/响应的转换、一些验证、确定要调用的业务组件并调用它们

    如果您一次只能执行一个,我建议您使用一个队列,例如JMSI已经在项目中使用JMS,我认为JMS对于这个简单的项目来说非常重要。如果您一次只能执行一个,我建议您使用一个队列,例如JMSI已经在项目中使用JMS,我认为JMS对于这个简单的项目来说非常重要。我不使用Netty、vetr.x、JMS,但我可以在EJB容器(@Singleton)中创建“线程部分”:
    @Path(/servicename”)公共类MyService{@Inject private RestService rs;@POST@Path(/compute)public void compute(){rs.computeimplement1();//包含执行器}
    否?也许可以;我不知道