0

Well,im trying to build a web applicattion in Java that starts a thread each time someone make a http request in the address. This is a good pratice? Could work?? Advantages or disadvantages? Work is below and use a spring example,just added the thread that i want

ps: This is running in tomcat

> HomeController.java

    @Controller  public class HomeController {

    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

    /**
     * Simply selects the home view to render by returning its name.
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Locale locale, Model model) {
        logger.info("Welcome home! The client locale is {}.", locale);

        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

        String formattedDate = dateFormat.format(date);

        model.addAttribute("serverTime", formattedDate );
        new Teste().start();
        return "home";
    }}class Teste extends Thread{

    @Override
    public void run() {

        while(true){
            System.out.println("im in thread");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }
    }

> web.xml

    <?xml version="1.0" encoding="UTF-8"?>  
<web-app version="2.5"xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/n/javaee/web-app_2_5.xsd">

    <!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/root-context.xml</param-value>
    </context-param>

    <!-- Creates the Spring Container shared by all Servlets and Filters -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Processes application requests -->
    <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

> servlet-context.xml

    <?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

    <context:component-scan base-package="com.example.threadTestes" />



</beans:beans>
user1866731
  • 481
  • 2
  • 5
  • 13

2 Answers2

2

threading in a managed environment is generally a bad idea. why not use some sort of abstraction like JMS to start a background handler every time someone sends a request ? that way you can control the number of active threads (jms pool size)

radai
  • 23,949
  • 10
  • 71
  • 115
  • And why is a bad idea? I need make the reqyest by http – user1866731 Dec 26 '12 at 15:35
  • 1
    your clients/users make GET requests, which are handled by tomcat (under its own, limited-size thread pool). if you were to just create a thread per request, and you have no control over how long your threads run you'll be vulnerable to all sorts of abuse. its better to queue up work in some well-established mechanism that can take care of pool size, retry etc for you instead of reinventing all that. also, JMS would allow you to scale out in the future by adding event handlers on other machines - clustering – radai Dec 26 '12 at 15:47
  • if you limit your thread count - by creating a work queue and a thread pool that feeds off it you've at least taken care of the problem of thread explosion. you'd still need to take care of things like queue overflow (write work queue to disk if its too big), queue persistence (what if your server was restarted with unfinished work? would you like to do it after restart? need to store it), job retries (if the work failed, should you retry? how many times?), scalability (if your work takes more power than you have and you want to use more machines) etc. jms does all this for you. – radai Dec 26 '12 at 15:53
  • Im asking this because my applicattion just need one request to start something that will run in background. So maybe i will just need one thread and just one... Why i need a thread? Because i want to make a request and after started the thread it return a Jsp to confirme that all is ok.. – user1866731 Dec 26 '12 at 15:58
  • then at the very least use a threadpool + workqueue (see here for a starting point: http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html). also, strictly speaking, most containers/specs (j2ee for example) prohibit threading in a managed application because the server is unaware of your new thread and cannot manage it (for example stop it to shutdown properly). if you do this all sorts of unexpected container (tomcat) behaviour might happen (it might not shut down properly, for example) – radai Dec 26 '12 at 16:00
  • Ah ok,the problem with threads in servlet container is that it cant stop the threads...? If is that,with executor i can stop the threads easily and dont need to worry about nothing more(i think) – user1866731 Dec 26 '12 at 16:04
1

Starting a thread for every request is terrible idea in any application, managed or unmanaged, and #1 reason for that is that amount of memory OS can use to allocate a stack for new thread is limited; and not only it's limited, it is shared between all processes on the box (though your java process may be allowed to use only part of that). Now imagine those threads won't terminate at all, or won't terminate fast enough as new requests keep coming in - OS will eventually run out of space for new threads; depending on the OS and it's settings, result may vary from rather fascinating OutOfMemoryError in new Thread(), to the whole box becoming apparently unresponsive, because your java process consumed all available space and no new threads can be created at all. So: 1) for handling requests use at least thread pool (Executor); JMS is an option if you need persistence, but again you handle requests in the pool - it's just fed from JMS 2) for some sort of maintainence tasks you can launch a separate thread during app startup. In both cases clean up after yourself and stop additional threads during shutdown.

Andrey Nudko
  • 697
  • 5
  • 5