1

I want to use Thread.sleep() in my java application. But does not work. Program works after removing sleep.

In my program I am running multiple threads and want that each move forward at a variable speed. Some may get executed more some less. So I am using sleep in each with a random number as argument. If there another way to do this. Without using sleep.

Here is the part where I am using the sleep function.

public void run()
    {
        Random r = new Random();
        int t;
        while(true)
        {
            if(total == 1)
            {
                // win();
                break;
            }
            if(doa == 1)
                break;
            // Player x = e[r.nextInt(20)%2];
            Player x = choose();
            x.attack(this, 10 + (power==1?5:0));
            if(r.nextInt(100)%(5 - (power==2?2:0)) == 0)
                System.out.println(" " + name + " used Potion effect (" + potionno++ + ") .. now " + name + "'s Health is " + (h+= 10 + r.nextInt(20))); 
            try
            {
                sleep(50 + r.nextInt(1000));
            }
            catch(InterruptedException c)
            {       ; }
        }
        if(doa == 1)) {
// and so on



   .

.

and here is my doGet function used for initiation

public void doGet(HttpServletRequest request, HttpServletResponse response)
           throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        String s;
        s = request.getParameter("name");           
        try{
           Player.out = out;
            Player.e[0] = new Player("Kartik",2);
            Player.e[1] = new Player(s,1);
            Player.e[2] = new Player("Anirudh",3);
            Player.e[3] = new Player("Vinita");
            Player.e[4] = new Player("Shivank");

            for(Player p: Player.   e)
                    p.start();

       }
           catch(Exception e)
           {
             out.print("WRONG");   
           }
    }
karx
  • 557
  • 2
  • 6
  • 16
  • 8
    We need to see your usage code. Also; are you sure you're not sleeping for an obscenely long time? If you just get a random int it could be very very large – Richard Tingle Jul 08 '13 at 12:28
  • 1
    It doesn't work because you are using `sleep` wrong, and not because using `sleep` is the wrong way to do what you want. – Marko Topolnik Jul 08 '13 at 12:29
  • 2
    @MarkoTopolnik you can see that he uses it wrong without code? Wow you need to give me your glasses... – WarrenFaith Jul 08 '13 at 12:30
  • @WarrenFaith It's not the glasses... – Marko Topolnik Jul 08 '13 at 12:31
  • 2
    @WarrenFaith I think Marko is using a process of elimination. Sleep isn't the wrong thing to do; so the usage of it must be wrong – Richard Tingle Jul 08 '13 at 12:31
  • 3
    We also need to know what "does not work" means, do you mean stops with an exception, will not compile or runs forever without printing a result – Richard Tingle Jul 08 '13 at 12:33
  • 1
    @RichardTingle - +1. it is excellent that you point out the OP didn't explain what *"does not work"* actually means. I've seen people trying these things when learning Java (God knows why they opt to use a servlet container out of all things to learn Java.) My guess (from the cases I've seen before) is that the OP was expecting the container (which he/she wrongly equates to his app) to freeze and come to a complete halt. Equating the container to the app, and thinking it as being single threaded is a common learning mistake. – luis.espinal Jul 08 '13 at 12:43
  • @luis.espinal I wonder if you have read the question. "I am running multiple threads and want that each move forward at a variable speed." – Marko Topolnik Jul 08 '13 at 13:10
  • 1
    OK, OP... now that you've given the code, can you say *how exactly is it not working for you*? There's nothing apparently wrong. In fact, I don't see how it "works without sleep" since then you are running a busy loop. – Marko Topolnik Jul 08 '13 at 13:36
  • @MarkoTopolnik - no, I did not read that because **it wasn't there.** :/ – luis.espinal Jul 08 '13 at 14:20
  • @luis.espinal That's funny because I have read it and it is present in the original version of the question. – Marko Topolnik Jul 08 '13 at 14:36
  • @MarkoTopolnik Its always worth remembering the 5 minute grace period before getting into arguments about who read what – Richard Tingle Jul 08 '13 at 14:55
  • @RichardTingle The question was posted at `12:27:57Z` and my earliest comment is at `12:29:27Z`. It took me at least 30 seconds to read and contemplate; that leaves a window of less than a minute within which luis had to load the page, read the stale text, then go on to pursue other interests, then come back to write his comment at `12:43:49Z`, without reloading the page, but *with* reloading comments. I consider my hypothesis much more likely. – Marko Topolnik Jul 08 '13 at 15:01
  • @MarkoTopolnik Fair enough, argue away. Remember though, people will always be being wrong on the internet – Richard Tingle Jul 08 '13 at 15:06
  • @RichardTingle Note that it's you now whose [duty calls](http://xkcd.com/386/) :) – Marko Topolnik Jul 08 '13 at 15:08
  • 1
    @MarkoTopolnik Well the first rule of the universe is that when I do it its ok – Richard Tingle Jul 08 '13 at 15:12
  • @MarkoTopolnik This java code works very well as a java application. The problem is when I try it on as a web application, when the page opens it shows the first few lines it should but does not run all the way.If i comment out the sleep part of the code, it runs all the way but not as I would like (as only one thread keeps on going and going). just to add I created a html page takes Player names and then sends it to my java page. (I am really new at this. I dont know if this is relevant or not but I am using NetBeans IDE -> Java Web Application) – karx Jul 09 '13 at 07:01
  • @user2560688 I'm afraid you are not giving the key information yet. How exactly do you start your application? If you start it through your own `public static void main` method, then you do not have a web application. – Marko Topolnik Jul 09 '13 at 07:18
  • @MarkoTopolnik It gets initiated in `public void doGet` please tell what all info I need to provide. Thanks – karx Jul 09 '13 at 08:28
  • Have you written `doGet` yourself? Then perhaps post it. – Marko Topolnik Jul 09 '13 at 08:30
  • @MarkoTopolnik Addded. please have a look. – karx Jul 09 '13 at 09:00
  • 1
    Yes, that looks quite wrong. It worked without sleep only by accident. You start a bunch of threads and immediately return from `doGet`, which means you complete the response. The threads then try to write into a closed writer, and die by IOException. – Marko Topolnik Jul 09 '13 at 09:10
  • What alternatives do I have. Please also add any referential reading I should consult to get me started and not do stupid things like this. – karx Jul 09 '13 at 09:11
  • I'll try to write another answer, but it won't be easy. – Marko Topolnik Jul 09 '13 at 09:12
  • @luis.espinal yes I am new to this and as you correctly figured i was expecting the container to work somewhat like a application. What are the alternatives that i have.. Thanks – karx Jul 09 '13 at 09:13
  • @MarkoTopolnik greatly appreciated – karx Jul 09 '13 at 09:13

2 Answers2

6

You shouldn't do that since, in general, Java EE/servlet containers work on the assumption their applications do not spawn threads (or modify the execution or configuration of existing ones, which you are doing with Thread.sleep()) of their own all nilly willy.

It is possible, but generally frowned upon unless you know what you are doing. See this answer that succinctly but excellently explains why: https://stackoverflow.com/a/533847/201722

As of why your call to Thread.sleep() doesn't work, it is because your servlet container is multi-threaded. Your call to Thread.sleep() is simply putting the thread that is handling your current HTTP request to sleep. But the container is still alive and kicking. If you send another HTTP request, it will grab another thread distinct from the one you put to sleep to handle it.

So, from your POV, it looks like it is not working. But it is working, you put the poor thread to sleep, and the container goes ok, here is another one for you. It just so happens you don't know what the heck is going on.

I would suggest you take the time to go through both the Java and the Java EE tutorials made available by Oracle (former Sun.) Google it and you will find it.

== EDIT ==

I would also recommend the OP to read the following succinct explanation against indiscriminately meddling with threads in a container.

http://www.psionicwave.com/blog/2012/12/15/threading-in-web-containers/

Community
  • 1
  • 1
luis.espinal
  • 10,331
  • 6
  • 39
  • 55
  • 1
    I generally agree with your answer but it should be moderated on the use of Threads in Servlet Containers, as your last link suggest. It is OK to spawn threads in a Servlet container. We do it all the time when talking to a JMS queue, when using futures or Actors, when scheduling with Quartz, etc.. Servlet 3.0 does it with its asynchronous model. It is just that manipulating threads is inherently complex, even more so within a Servlet Container. – Bruno Grieder Jul 09 '13 at 09:26
  • 1
    @BGR The rule is to ask the container for each specific service which involves threads (such as those you mention), and to never use `new Thread()` in client code. – Marko Topolnik Jul 09 '13 at 09:51
2

Many things are wrong with your current approach, I'll try to point out some.

  1. Your Player apparently extends Thread. That's an antipattern; you should only implements Runnable and pass the instance of your class to new Thread();

  2. the basic flavor of a Servlet-based Web application is based on a strict request-response paradigm, where the respone happens as soon as possible. What you (possibly) are looking for is a "long response", asynchronous style. This can be achieved with new features in Servlet 3.0, but is well beyond the scope of this answer;

  3. assuming for a moment that you just want a go at it, a quick patch is to append

    for (Player p : Player.e) p.join();
    

    to your existing doGet method. This will postpone the returning of doGet until all your subthreads die. You will also need to routinely flush the writer to force the immediate sending of the data to the client side (or use PrintWriter#println, which has auto-flush semantics).

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • Thanks a ton. Does so what it is suppose to. Will look into Servlet 3.0 for more info. – karx Jul 09 '13 at 09:45