Powered by Blogger.

Thread.sleep() in Java - Thread Sleep Method in Java

Thread Sleep Method in Java:

Syntax:

      public static void Sleep(
      int millisecondsTimeout
      )

Parameters:

millisecondsTimeout
Type: System.Int32

The number of milliseconds for which the thread is blocked. Specify zero (0) to indicate that this thread should be suspended to allow other waiting threads to execute. Specify Infinite to block the thread indefinitely.

Examples:

        The following example uses the Sleep method to block the application's main thread.

using System;
using System.Threading;

class Example
{
    static void Main()
    {
        for (int i = 0; i < 5; i++)
        {
            Console.WriteLine("Sleep for 2 seconds.");
            Thread.Sleep(2000);
        }

        Console.WriteLine("Main thread exits.");
    }
}

/* This example produces the following output:

Sleep for 2 seconds.
Sleep for 2 seconds.
Sleep for 2 seconds.
Sleep for 2 seconds.
Sleep for 2 seconds.
Main thread exits.
 */

Threading:

This chapter is excerpted from C# 3.0 in a Nutshell, Third Edition: A Desktop Quick Reference by Joseph Albahari, Ben Albahari, published by O'Reilly Media C# 3.0 in a Nutshell, Third Edition Logo Buy Now C# allows you to execute code in parallel through multithreading.

A thread is analogous to the operating system process in which your application runs. Just as processes run in parallel on a computer, threads run in parallel within a single process. Processes are fully isolated from each other; threads have just a limited degree of isolation. In particular, threads share (heap) memory with other threads running in the same application domain. This, in part, is why threading is useful: one thread can fetch data in the background while another thread displays the data as it arrives.

This chapter describes the language and Framework features for creating, configuring, and communicating with threads, and how to coordinate their actions through locking and signaling. It also covers the predefined types that assist threading: BackgroundWorker, ReaderWriterLock, and the Timer classes.


Threading's Uses and Misuses:

A common use for multithreading is to maintain a responsive user interface while a time-consuming task executes. If the time-consuming task runs on a parallel "worker" thread, the main thread is free to continue processing keyboard and mouse events.

Whether or not a user interface is involved, multithreading can be useful when awaiting a response from another computer or piece of hardware. If a worker thread performs the task, the instigator is immediately free to do other things, taking advantage of the otherwise unburdened computer.

Another use for multithreading is in writing methods that perform intensive calculations. Such methods can execute faster on a multiprocessor or multicore computer if the workload is shared among two or more threads. Asynchronous delegates are particularly well suited to this. (You can test for the number of processors via the Environment. Processor Count property.)

Some features of the .NET Framework implicitly create threads. If you use ASP.NET, WCF, Web Services, or Remoting, incoming client requests can arrive concurrently on the server. You may be unaware that multithreading is taking place; unless, perhaps, you use static fields to cache data without appropriate locking, running afoul of thread safety.

Threads also come with strings attached. The biggest is that multithreading can increase complexity. Having lots of threads does not in itself create complexity; it's the interaction between threads (typically via shared data) that does. This applies whether or not the interaction is intentional, and can cause long development cycles and an ongoing susceptibility to intermittent and nonreproducible bugs. For this reason, it pays to keep interaction to a minimum, and to stick to simple and proven designs wherever possible. This chapter is largely on dealing with just these complexities; remove the interaction and there's relatively little to say!

Threading also comes with a resource and CPU cost in allocating and switching threads. Multithreading will not always speed up your application-it can even slow it down if used excessively or inappropriately. For example, when heavy disk I/O is involved, it can be faster to have a couple of worker threads run tasks in sequence than to have 10 threads executing at once. (In the later section "the section called "Signaling with Wait and Pulse" we describe how to implement a producer/consumer queue, which provides just this functionality.)

Getting Started:

A C# program starts in a single thread that's created automatically by the CLR and operating system (the "main" thread). Here it lives out its life as a single-threaded application, unless you do otherwise, by creating more threads (directly or indirectly).

The simplest way to create a thread is to instantiate a Thread object and to call its Start method. The constructor for Thread takes a Thread Start delegate: a parameterless method indicating where execution should begin. Here's an example:

class ThreadTest
{
  static void Main(  )
  {
    Thread t = new Thread (WriteY);          // Kick off a new thread
    t.Start();                               // running WriteY(  )

    // Simultaneously, do something on the main thread.
    for (int i = 0; i < 1000; i++) Console.Write ("x");
  }

  static void WriteY(  )
  {
    for (int i = 0; i < 1000; i++) Console.Write ("y");
  }
}

// Output:
xxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyy
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
yyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
............

The sleep() is a static method in the Thread class, it operates on the current thread and is referred to as Thread.sleep(x); where x is the minimum number of millisecond.

1  public class ThreadSleep implements Runnable{
2     public void run(){
3       int i=1;
4       while(i<=10){
5         System.out.println(”i:”+i);
6         i++;
7         try{
8            Thread.sleep(300);
9         }catch(InterruptedException e){
10           System.out.println(e);
11        }
12      }
13   }
14
15   public static void main (String[]args){
16     ThreadSleep ts = new ThreadSleep();
17     Thread thread1 = new Thread(ts);
18     Thread thread2 = new Thread(ts);
19     Thread thread3 = new Thread(ts);
20     thread1.start();
21     thread2.start();
22     thread3.start();
23   }
24 }

Synchronization:

So far, we've described how to start a task on a thread, how to configure a thread, and how to pass data in both directions. We've also described how local variables are private to a thread and how references can be shared among threads allowing them to communicate via common fields.

The next step is synchronization: coordinating the actions of threads for a predictable outcome. Synchronization is particularly important when threads access the same data; it's surprisingly easy to run aground in this area.

Synchronization constructs can be divided into four categories:

Simple Blocking Methods

These wait for another thread to finish or for a period of time to elapse. Sleep, Join, and EndInvoke are simple blocking methods.

Locking constructs:

These enforce exclusive access to a resource, such as a field or section of code, ensuring that only one thread can enter at a time. Locking is the primary thread-safety mechanism, allowing threads to access common data without interfering with each other. The locking constructs are lock and Mutex (and a variation called Semaphore).

Signaling constructs:

These allow a thread to pause until receiving a notification from another, avoiding the need for inefficient polling. There are two signaling devices: event wait handles and Monitor's Wait/Pulse methods.

Nonblocking synchronization constructs:

These protect access to a common field by calling upon processor primitives. The Interlocked class and the volatile keyword are the two constructs in this category.

Blocking is essential to all but the last category. Let's briefly examine this concept.

Code: The StackTest.java application

1   class MyStack{
2     private int idx=0;
3     private char[] data = new char[6];
4
5     public synchronized void push(char c){
6      this.notify();
7      if(idx !=5){
8         data[idx]=c;
9         idx++;
10     }
11   }
12
13   public synchronized char pop(){
14     if(idx==0){
15        try{
16           this.wait();
17        }catch(InterruptedException e ){
18           System.out.println(e);
19        }
20     }
21     idx−−;
22     return data[idx];
23   }
24 }
25
26 class Producer implements Runnable{
27   private MyStack stack;
28
29   public Producer(MyStack s){
30     stack = s;
31   }
32
33   public void run(){
34     char c;
35     for(int i=0; i<50; i++){
36         c = (char) (Math.random()*26+’A’);
37         stack.push(c);
38         System.out.println(”Producer:”+c);
39         try{
40            Thread.sleep((int)(Math.random()*300));
41         }catch(InterruptedException e){
42            System.out.println(e);
43         }
44      }
45    }
46  }
47


48  class Consumer implements Runnable{
49    private MyStack stack;
50
51    public Consumer(MyStack s){
52      stack = s;
53    }
54
55    public void run(){
56      char c;
57      for(int i=0; i<50; i++){
58          c = stack.pop();
59          System.out.println(”Consumer:”+c);
60          try{
61             Thread.sleep((int)(Math.random()*300));
62          }catch(InterruptedException e){
63             System.out.println(e);
64          }
65      }
66    }
67 }
68
69 public class StackTest{
70   public static void main(String[]args){
71     MyStack s = new MyStack();
72     Producer p = new Producer(s);
73     Thread t1 = new Thread(p);
74     t1.start();
75     Consumer c = new Consumer(s);
76     Thread t2 = new Thread(c);
77     t2.start();
78   }
79 }

Locking:

Exclusive locking is used to ensure that only one thread can enter particular sections of code at a time. The .NET Framework provides two exclusive locking constructs: lock and Mutex. Of the two, the lock construct is faster and more convenient. Mutex, though, has a niche in that its lock can span applications in different processes on the computer.

This section focuses on the lock construct; later we show how Mutex can be used for cross-process locking. Finally, we introduce Semaphore, .NET's nonexclusive locking construct.

Let's start with the following class:

class ThreadUnsafe
{
  static int val1, val2;

  static void Go(  )
  {
    if (val2 != 0) Console.WriteLine (val1 / val2);
    val2 = 0;
  }
}

This class is not thread-safe: if Go was called by two threads simultaneously, it would be possible to get a division-by-zero error, because val2 could be set to zero in one thread right as the other thread was in between executing the if statement and Console. Write Line.

Here's how lock can fix the problem:

class ThreadSafe
{
  static object locker = new object(  );
  static int val1, val2;

  static void Go(  )
  {
    lock (locker)
    {
      if (val2 != 0) Console.WriteLine (val1 / val2);
      val2 = 0;
    }
  }
}

Only one thread can lock the synchronizing object (in this case, locker) at a time, and any contending threads are blocked until the lock is released. If more than one thread contends the lock, they are queued on a "ready queue" and granted the lock on a first-come, first-served basis. Exclusive locks are sometimes said to enforce serialized access to whatever's protected by the lock, because one thread's access cannot overlap with that of another. In this case, we're protecting the logic inside the Go method, as well as the fields val1 and val2.

A thread blocked while awaiting a contended lock has a Thread State of Wait Sleep Join. In the section "the section called "Interrupt and Abort"," later in this chapter, we describe how a blocked thread can be forcibly released via another thread. This is a fairly heavy-duty technique that might be used in ending a thread.

C#'s lock statement is in fact a syntactic shortcut for a call to the methods Monitor.Enter and Monitor.Exit, with a try-finally block. Here's what's actually happening within the Go method of the preceding example:

Monitor.Enter (locker);
try
{
  if (val2 != 0) Console.WriteLine (val1 / val2);
  val2 = 0;
}
finally { Monitor.Exit (locker); }

Calling Monitor.Exit without first calling Monitor.Enter on the same object throws an exception.

Monitor also provides a Try Enter method that allows a timeout to be specified, either in milliseconds or as a Time Span. The method then returns true if a lock was obtained, or false if no lock was obtained because the method timed out. Try Enter can also be called with no argument, which "tests" the lock, timing out immediately if the lock can't be obtained right away.


Nested Locking:

A thread can repeatedly lock the same object, via multiple calls to Monitor.Enter, or nested lock statements. The object is subsequently unlocked when a corresponding number of Monitor.Exit statements have executed or when the outermost lock statement has exited. This allows for the most natural semantics when one method calls another as follows:

static object x = new object(  );

static void Main(  )
{
  lock (x)
  {
     Console.WriteLine ("I have the lock");
     Nest(  );
     Console.WriteLine ("I still have the lock");
  }
  // Now the lock is released.
}

static void Nest(  )
{
  lock (x) { }
  // We still have the lock on x!
}

A thread can block on only the first, or outermost, lock.

0 comments:

Post a Comment