Processes and Threads

When an application component starts and the application does not have any other components running, the Android system starts a new Linux process for the application with a single thread of execution. By default, all components of the same application run in the same process and thread (called the “main” thread). If an application component starts and there already exists a process for that application (because another component from the application exists), then the component is started within that process and uses the same thread of execution. However, you can arrange for different components in your application to run in separate processes, and you can create additional threads for any process.

This document discusses how processes and threads work in an Android application.

Processes


By default, all components of the same application run in the same process and most applications should not change this. However, if you find that you need to control which process a certain component belongs to, you can do so in the manifest file.

The manifest entry for each type of component element—<activity>, <service>, <receiver>, and<provider>—supports an android:process attribute that can specify a process in which that component should run. You can set this attribute so that each component runs in its own process or so that some components share a process while others do not. You can also set android:process so that components of different applications run in the same process—provided that the applications share the same Linux user ID and are signed with the same certificates.

The <application> element also supports an android:process attribute, to set a default value that applies to all components.

Android might decide to shut down a process at some point, when memory is low and required by other processes that are more immediately serving the user. Application components running in the process that’s killed are consequently destroyed. A process is started again for those components when there’s again work for them to do.

When deciding which processes to kill, the Android system weighs their relative importance to the user. For example, it more readily shuts down a process hosting activities that are no longer visible on screen, compared to a process hosting visible activities. The decision whether to terminate a process, therefore, depends on the state of the components running in that process. The rules used to decide which processes to terminate is discussed below.

Process lifecycle

The Android system tries to maintain an application process for as long as possible, but eventually needs to remove old processes to reclaim memory for new or more important processes. To determine which processes to keep and which to kill, the system places each process into an “importance hierarchy” based on the components running in the process and the state of those components. Processes with the lowest importance are eliminated first, then those with the next lowest importance, and so on, as necessary to recover system resources.

There are five levels in the importance hierarchy. The following list presents the different types of processes in order of importance (the first process is most important and is killed last):

  1. Foreground processA process that is required for what the user is currently doing. A process is considered to be in the foreground if any of the following conditions are true:

    Generally, only a few foreground processes exist at any given time. They are killed only as a last resort—if memory is so low that they cannot all continue to run. Generally, at that point, the device has reached a memory paging state, so killing some foreground processes is required to keep the user interface responsive.

  2. Visible processA process that doesn’t have any foreground components, but still can affect what the user sees on screen. A process is considered to be visible if either of the following conditions are true:
    • It hosts an Activity that is not in the foreground, but is still visible to the user (its onPause()method has been called). This might occur, for example, if the foreground activity started a dialog, which allows the previous activity to be seen behind it.
    • It hosts a Service that’s bound to a visible (or foreground) activity.

    A visible process is considered extremely important and will not be killed unless doing so is required to keep all foreground processes running.

  3. Service processA process that is running a service that has been started with the startService() method and does not fall into either of the two higher categories. Although service processes are not directly tied to anything the user sees, they are generally doing things that the user cares about (such as playing music in the background or downloading data on the network), so the system keeps them running unless there’s not enough memory to retain them along with all foreground and visible processes.
  4. Background processA process holding an activity that’s not currently visible to the user (the activity’s onStop() method has been called). These processes have no direct impact on the user experience, and the system can kill them at any time to reclaim memory for a foreground, visible, or service process. Usually there are many background processes running, so they are kept in an LRU (least recently used) list to ensure that the process with the activity that was most recently seen by the user is the last to be killed. If an activity implements its lifecycle methods correctly, and saves its current state, killing its process will not have a visible effect on the user experience, because when the user navigates back to the activity, the activity restores all of its visible state. See the Activities document for information about saving and restoring state.
  5. Empty processA process that doesn’t hold any active application components. The only reason to keep this kind of process alive is for caching purposes, to improve startup time the next time a component needs to run in it. The system often kills these processes in order to balance overall system resources between process caches and the underlying kernel caches.

Android ranks a process at the highest level it can, based upon the importance of the components currently active in the process. For example, if a process hosts a service and a visible activity, the process is ranked as a visible process, not a service process.

In addition, a process’s ranking might be increased because other processes are dependent on it—a process that is serving another process can never be ranked lower than the process it is serving. For example, if a content provider in process A is serving a client in process B, or if a service in process A is bound to a component in process B, process A is always considered at least as important as process B.

Because a process running a service is ranked higher than a process with background activities, an activity that initiates a long-running operation might do well to start a service for that operation, rather than simply create a worker thread—particularly if the operation will likely outlast the activity. For example, an activity that’s uploading a picture to a web site should start a service to perform the upload so that the upload can continue in the background even if the user leaves the activity. Using a service guarantees that the operation will have at least “service process” priority, regardless of what happens to the activity. This is the same reason that broadcast receivers should employ services rather than simply put time-consuming operations in a thread.

Threads


When an application is launched, the system creates a thread of execution for the application, called “main.” This thread is very important because it is in charge of dispatching events to the appropriate user interface widgets, including drawing events. It is also the thread in which your application interacts with components from the Android UI toolkit (components from the android.widget andandroid.view packages). As such, the main thread is also sometimes called the UI thread.

The system does not create a separate thread for each instance of a component. All components that run in the same process are instantiated in the UI thread, and system calls to each component are dispatched from that thread. Consequently, methods that respond to system callbacks (such asonKeyDown() to report user actions or a lifecycle callback method) always run in the UI thread of the process.

For instance, when the user touches a button on the screen, your app’s UI thread dispatches the touch event to the widget, which in turn sets its pressed state and posts an invalidate request to the event queue. The UI thread dequeues the request and notifies the widget that it should redraw itself.

When your app performs intensive work in response to user interaction, this single thread model can yield poor performance unless you implement your application properly. Specifically, if everything is happening in the UI thread, performing long operations such as network access or database queries will block the whole UI. When the thread is blocked, no events can be dispatched, including drawing events. From the user’s perspective, the application appears to hang. Even worse, if the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with the infamous “application not responding” (ANR) dialog. The user might then decide to quit your application and uninstall it if they are unhappy.

Additionally, the Andoid UI toolkit is not thread-safe. So, you must not manipulate your UI from a worker thread—you must do all manipulation to your user interface from the UI thread. Thus, there are simply two rules to Android’s single thread model:

  1. Do not block the UI thread
  2. Do not access the Android UI toolkit from outside the UI thread

Worker threads

Because of the single thread model described above, it’s vital to the responsiveness of your application’s UI that you do not block the UI thread. If you have operations to perform that are not instantaneous, you should make sure to do them in separate threads (“background” or “worker” threads).

For example, below is some code for a click listener that downloads an image from a separate thread and displays it in an ImageView:

public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            Bitmap b = loadImageFromNetwork("http://example.com/image.png");
            mImageView.setImageBitmap(b);
        }
    }).start();
}

At first, this seems to work fine, because it creates a new thread to handle the network operation. However, it violates the second rule of the single-threaded model: do not access the Android UI toolkit from outside the UI thread—this sample modifies the ImageView from the worker thread instead of the UI thread. This can result in undefined and unexpected behavior, which can be difficult and time-consuming to track down.

To fix this problem, Android offers several ways to access the UI thread from other threads. Here is a list of methods that can help:

For example, you can fix the above code by using the View.post(Runnable) method:

public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            final Bitmap bitmap =
                    loadImageFromNetwork("http://example.com/image.png");
            mImageView.post(new Runnable() {
                public void run() {
                    mImageView.setImageBitmap(bitmap);
                }
            });
        }
    }).start();
}

Now this implementation is thread-safe: the network operation is done from a separate thread while theImageView is manipulated from the UI thread.

However, as the complexity of the operation grows, this kind of code can get complicated and difficult to maintain. To handle more complex interactions with a worker thread, you might consider using aHandler in your worker thread, to process messages delivered from the UI thread. Perhaps the best solution, though, is to extend the AsyncTask class, which simplifies the execution of worker thread tasks that need to interact with the UI.

Using AsyncTask

AsyncTask allows you to perform asynchronous work on your user interface. It performs the blocking operations in a worker thread and then publishes the results on the UI thread, without requiring you to handle threads and/or handlers yourself.

To use it, you must subclass AsyncTask and implement the doInBackground() callback method, which runs in a pool of background threads. To update your UI, you should implementonPostExecute(), which delivers the result from doInBackground() and runs in the UI thread, so you can safely update your UI. You can then run the task by calling execute() from the UI thread.

For example, you can implement the previous example using AsyncTask this way:

public void onClick(View v) {
    new DownloadImageTask().execute("http://example.com/image.png");
}

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    /** The system calls this to perform work in a worker thread and
      * delivers it the parameters given to AsyncTask.execute() */
    protected Bitmap doInBackground(String... urls) {
        return loadImageFromNetwork(urls[0]);
    }

    /** The system calls this to perform work in the UI thread and delivers
      * the result from doInBackground() */
    protected void onPostExecute(Bitmap result) {
        mImageView.setImageBitmap(result);
    }
}

Now the UI is safe and the code is simpler, because it separates the work into the part that should be done on a worker thread and the part that should be done on the UI thread.

You should read the AsyncTask reference for a full understanding on how to use this class, but here is a quick overview of how it works:

Caution: Another problem you might encounter when using a worker thread is unexpected restarts in your activity due to a runtime configuration change (such as when the user changes the screen orientation), which may destroy your worker thread. To see how you can persist your task during one of these restarts and how to properly cancel the task when the activity is destroyed, see the source code for the Shelves sample application.

Thread-safe methods

In some situations, the methods you implement might be called from more than one thread, and therefore must be written to be thread-safe.

This is primarily true for methods that can be called remotely—such as methods in a bound service. When a call on a method implemented in an IBinder originates in the same process in which theIBinder is running, the method is executed in the caller’s thread. However, when the call originates in another process, the method is executed in a thread chosen from a pool of threads that the system maintains in the same process as the IBinder (it’s not executed in the UI thread of the process). For example, whereas a service’s onBind() method would be called from the UI thread of the service’s process, methods implemented in the object that onBind() returns (for example, a subclass that implements RPC methods) would be called from threads in the pool. Because a service can have more than one client, more than one pool thread can engage the same IBinder method at the same time.IBinder methods must, therefore, be implemented to be thread-safe.

Similarly, a content provider can receive data requests that originate in other processes. Although theContentResolver and ContentProvider classes hide the details of how the interprocess communication is managed, ContentProvider methods that respond to those requests—the methodsquery(), insert(), delete(), update(), and getType()—are called from a pool of threads in the content provider’s process, not the UI thread for the process. Because these methods might be called from any number of threads at the same time, they too must be implemented to be thread-safe.

Interprocess Communication


Android offers a mechanism for interprocess communication (IPC) using remote procedure calls (RPCs), in which a method is called by an activity or other application component, but executed remotely (in another process), with any result returned back to the caller. This entails decomposing a method call and its data to a level the operating system can understand, transmitting it from the local process and address space to the remote process and address space, then reassembling and reenacting the call there. Return values are then transmitted in the opposite direction. Android provides all the code to perform these IPC transactions, so you can focus on defining and implementing the RPC programming interface.

To perform IPC, your application must bind to a service, using bindService(). For more information, see the Services developer guide.

Network discovery using UDP Broadcast (Java)

The Problem

I have a Java server and a Java client running on the same network and the applications are not to be used outside a private network (not over internet). So I used a static IP for the server, but what if I deploy my application? What if the network changes? That means I’ll lose my connection to the server and I’ll have to change the IP on the client side again. Now that would be stupid. I want the client to “discover” the server on the network and connect with it.


The Solution

Using UDP packets and broadcasting them! This technique however is not optimal, but as long as we stay in one network this shouldn’t be a problem. UDP packets however are fairly easy to work with. So let’s get started.


Still here? Let’s do this!

Server implementation

First, Let’s create the Java Singleton class that will execute the code on the server-side. This will be multi-threaded of course,  so we’ll also implement “Runnable”. When we implement Runnable, we also have to override the Run method.

public class DiscoveryThread implements Runnable {

  @Override
  public void run() {
  }

  public static DiscoveryThread getInstance() {
    return DiscoveryThreadHolder.INSTANCE;
  }

  private static class DiscoveryThreadHolder {

    private static final DiscoveryThread INSTANCE = new DiscoveryThread();
  }

}

Ok, let’s think about this. What do we have to do?

  1. Open a socket on the server that listens to the UDP requests. (I’ve chosen 8888)
  2. Make a loop that handles the UDP requests and responses
  3. Inside the loop, check the received UPD packet to see if it’s valid
  4. Still inside the loop, send a response to the IP and Port of the received packet

That’s it on the server side.

Now, we’ll translate this into code.

DatagramSocket socket;

  @Override
  public void run() {
    try {
      //Keep a socket open to listen to all the UDP trafic that is destined for this port
      socket = new DatagramSocket(8888, InetAddress.getByName("0.0.0.0"));
      socket.setBroadcast(true);

      while (true) {
        System.out.println(getClass().getName() + ">>>Ready to receive broadcast packets!");

        //Receive a packet
        byte[] recvBuf = new byte[15000];
        DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
        socket.receive(packet);

        //Packet received
        System.out.println(getClass().getName() + ">>>Discovery packet received from: " + packet.getAddress().getHostAddress());
        System.out.println(getClass().getName() + ">>>Packet received; data: " + new String(packet.getData()));

        //See if the packet holds the right command (message)
        String message = new String(packet.getData()).trim();
        if (message.equals("DISCOVER_FUIFSERVER_REQUEST")) {
          byte[] sendData = "DISCOVER_FUIFSERVER_RESPONSE".getBytes();

          //Send a response
          DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, packet.getAddress(), packet.getPort());
          socket.send(sendPacket);

          System.out.println(getClass().getName() + ">>>Sent packet to: " + sendPacket.getAddress().getHostAddress());
        }
      }
    } catch (IOException ex) {
      Logger.getLogger(DiscoveryThread.class.getName()).log(Level.SEVERE, null, ex);
    }
  }

A few notes; If you want to use strings as commands (like I do in this example), you have to trim the string before comparing it.

There, that’s it for the server.

Client implementation

Now we have to write the code for the client. Again, let me sketch how we are going to work.

  1. Open a socket on a random port.
  2. Try to broadcast to the default broadcast address (255.255.255.255)
  3. Loop over all the computer’s network interfaces and get their broadcast addresses
  4. Send the UDP packet inside the loop to the interface’s broadcast address
  5. Wait for a reply
  6. When we have a reply, check to see if the package is valid
  7. When it’s valid, get the package’s sender IP address; this is the server’s IP address
  8. CLOSE the socket! We don’t want to leave open random ports on someone else’s computer

On a side note, we don’t close the socket on the server because the server will receive and send UPD packets until the server is closed. Closing the socket on the server means that we won’t be able to discover it any more.

Wow, that was quite a lot. Now let’s put this into code!

// Find the server using UDP broadcast
try {
  //Open a random port to send the package
  c = new DatagramSocket();
  c.setBroadcast(true);

  byte[] sendData = "DISCOVER_FUIFSERVER_REQUEST".getBytes();

  //Try the 255.255.255.255 first
  try {
    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("255.255.255.255"), 8888);
    c.send(sendPacket);
    System.out.println(getClass().getName() + ">>> Request packet sent to: 255.255.255.255 (DEFAULT)");
  } catch (Exception e) {
  }

  // Broadcast the message over all the network interfaces
  Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
  while (interfaces.hasMoreElements()) {
    NetworkInterface networkInterface = interfaces.nextElement();

    if (networkInterface.isLoopback() || !networkInterface.isUp()) {
      continue; // Don't want to broadcast to the loopback interface
    }

    for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) {
      InetAddress broadcast = interfaceAddress.getBroadcast();
      if (broadcast == null) {
        continue;
      }

      // Send the broadcast package!
      try {
        DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, broadcast, 8888);
        c.send(sendPacket);
      } catch (Exception e) {
      }

      System.out.println(getClass().getName() + ">>> Request packet sent to: " + broadcast.getHostAddress() + "; Interface: " + networkInterface.getDisplayName());
    }
  }

  System.out.println(getClass().getName() + ">>> Done looping over all network interfaces. Now waiting for a reply!");

  //Wait for a response
  byte[] recvBuf = new byte[15000];
  DatagramPacket receivePacket = new DatagramPacket(recvBuf, recvBuf.length);
  c.receive(receivePacket);

  //We have a response
  System.out.println(getClass().getName() + ">>> Broadcast response from server: " + receivePacket.getAddress().getHostAddress());

  //Check if the message is correct
  String message = new String(receivePacket.getData()).trim();
  if (message.equals("DISCOVER_FUIFSERVER_RESPONSE")) {
    //DO SOMETHING WITH THE SERVER'S IP (for example, store it in your controller)
    Controller_Base.setServerIp(receivePacket.getAddress());
  }

  //Close the port!
  c.close();
} catch (IOException ex) {
  Logger.getLogger(LoginWindow.class.getName()).log(Level.SEVERE, null, ex);
}

I’ve given you pretty much all of the code, so it shouldn’t be easy to implement. Don’t forget to run your DiscoveryThread!

Thread discoveryThread = new Thread(DiscoveryThread.getInstance());
    discoveryThread.start();

Handling network timeouts in Java

When writing network applications in a stable and controlled environment, it is easy to forget what the real world is like. Slow connections, traffic build ups, or power interruptions can cause network connections to stall or even die. Few programmers take the time to detect and handle network timeouts, but avoiding the problem can cause client applications to freeze, and for threads in servers to block indefinitely. There are, however, easy ways to handle network timeouts. In this article, I’ll present two techniques for overcoming the problem of network timeouts – threads and setting a socket option for timeouts.

Overview

Handling timeouts is one of those tasks that people generally leave to the last moment. In an ideal world, we’d never need them. In an intranet environment, where most programmers do their development, it’s almost always unnecessary. However, on the Internet, good timeout handling is critical. Badly behaved clients may go offline and leaving server threads locked, or overloaded servers may stall, causing a network client to block indefinitely for input. For these reasons, it is necessary to detect and handle network timeouts.

I’ve identified two relatively simple solutions to the problem of handling network timeouts. The first solution involves the use of second thread, which acts as a timer. This solution results in a slight increase in complexity, but is backwards compatible with JDK1.02. The second solution is by far, much simpler. It takes only a few lines of code, by setting a socket option, and catching a timeout exception. The catch is, that it requires a JDK1.1 or higher virtual machine.

Solution One : Using a timer thread

Many network software (particularly servers), are written as multi-threaded applications. However, a client can also use multiple threads. One solution to handling network timeouts is to launch a secondary thread, the ‘timer’, and have it cancel the application gracefully if it becomes stalled. This prevents end users from becoming confused when the application stalls – a good error message will at least let them know the cause of the problem.

Listing One shows a Timer, which can be used in networking applications to handle timeouts gracefully. Once the timer is started, it must be reset regularly, such as when data is returned by a server. However, if the thread that reads from a remote network host becomes stalled, the timer will exit with an error message. For those who require a custom handler, the timeout() method may be overridden to provide different functionality.


Listing One – Timer.java

/** 
  * The Timer class allows a graceful exit when an application
  * is stalled due to a networking timeout. Once the timer is
  * set, it must be cleared via the reset() method, or the
  * timeout() method is called.
  * <p>
  * The timeout length is customizable, by changing the 'length'
  * property, or through the constructor. The length represents
  * the length of the timer in milliseconds.
  *
  * @author	David Reilly
  */
public class Timer extends Thread
{
	/** Rate at which timer is checked */
	protected int m_rate = 100;
	
	/** Length of timeout */
	private int m_length;

	/** Time elapsed */
	private int m_elapsed;

	/**
	  * Creates a timer of a specified length
	  * @param	length	Length of time before timeout occurs
	  */
	public Timer ( int length )
	{
		// Assign to member variable
		m_length = length;

		// Set time elapsed
		m_elapsed = 0;
	}

	
	/** Resets the timer back to zero */
	public synchronized void reset()
	{
		m_elapsed = 0;
	}

	/** Performs timer specific code */
	public void run()
	{
		// Keep looping
		for (;;)
		{
			// Put the timer to sleep
			try
			{ 
				Thread.sleep(m_rate);
			}
			catch (InterruptedException ioe) 
			{
				continue;
			}

			// Use 'synchronized' to prevent conflicts
			synchronized ( this )
			{
				// Increment time remaining
				m_elapsed += m_rate;

				// Check to see if the time has been exceeded
				if (m_elapsed > m_length)
				{
					// Trigger a timeout
					timeout();
				}
			}

		}
	}

	// Override this to provide custom functionality
	public void timeout()
	{
		System.err.println ("Network timeout occurred.... terminating");
		System.exit(1);
	}
}

To illustrate the use of the Timer class, here is a simple TCP client (Listing Two) and server (Listing Three). The client sends a text string across the network, and then reads a response. While reading, it would become blocked if the server stalled, or if the server took too long to accept the connection. For this reason, a timer is started before connecting, and then reset after each major operation. Starting the timer is relatively simple, but it must be reset after each blocking operation or the client will terminate.

// Start timer
Timer timer = new Timer(3000);
timer.start();

// Perform some read operation
......

// Reset the timer
timer.reset();

The server is relatively simple – it’s a single-threaded application, which simulates a stalled server. The server reads a response from the client, and echoes it back.To demonstrate timeouts, the server will always “stall” for a period of twenty seconds, on every second connection. Remember though, in real life, server timeouts are entirely unpredictable, and will not always correct themselves after several seconds of delay.


Listing Two

import java.net.*;
import java.io.*;

/**
  * SimpleClient connects to TCP port 2000, writes a line
  * of text, and then reads the echoed text back from the server.
  * This client will detect network timeouts, and exit gracefully,
  * rather than stalling.
  * Start server, and the run by typing
  *
  *  java SimpleClient
  */
public class SimpleClient
{
	/** Connects to a server on port 2000,
	    and handles network timeouts gracefully 
	  */
	public static void main (String args[]) throws Exception
	{
		System.out.println ("Starting timer.");
		// Start timer
		Timer timer = new Timer(3000);
		timer.start();

		// Connect to remote host
		Socket socket = new Socket ("localhost", 2000);
		System.out.println ("Connected to localhost:2000");

		// Reset timer - timeout can occur on connect
		timer.reset();

		// Create a print stream for writing
		PrintStream pout = new PrintStream ( 
			socket.getOutputStream() );

		// Create a data input stream for reading
		DataInputStream din = new DataInputStream( 
			socket.getInputStream() );

		// Print hello msg
		pout.println ("Hello world!");

		// Reset timer - timeout is likely to occur during the read
		timer.reset();

		// Print msg from server
		System.out.println (din.readLine());

		// Shutdown timer
		timer.stop();

		// Close connection
		socket.close();
	}
}

Listing Three

import java.net.*;
import java.io.*;

/**
  * SimpleServer binds to TCP port 2000, reads a line
  * of text, and then echoes it back to the user. To
  * demonstrate a network timeout, every second connection
  * will stall for twenty seconds.
  *
  * Start server by typing
  *
  *  java SimpleServer
  */
public class SimpleServer extends Thread
{
	/** Shall we stall? flag */
	protected static boolean shallWeStall = false;

	/** Socket connection */
	private Socket m_connection;

	/**
	  * Constructor, accepting a socket connection
	  *	@param	connection	Connection to process
	  */
	public SimpleServer (Socket connection)
	{
		// Assign to member variable
		m_connection = connection;
	}

	/** Starts a simple server on port 2000 */
	public static void main (String args[]) throws Exception
	{
		ServerSocket server = new ServerSocket (2000);

		for (;;)
		{
			// Accept an incoming connection
			Socket connection = server.accept();

			// Process in another thread
			new SimpleServer(connection).start();
		}
	}

	/** Performs connection handling */
	public void run()
	{
		try
		{
			DataInputStream din = new DataInputStream (
				m_connection.getInputStream() );

			PrintStream pout = new PrintStream (
				m_connection.getOutputStream() );

			// Read line from client
			String data = din.readLine();

			// Check to see if we should simulate a stalled server
			if (shallWeStall)
			{
				// Yes .. so reset flag and stall
				shallWeStall = false;

				try
				{
					Thread.sleep (20000);
				} catch (InterruptedException ie ) {}
			}
			else
			{
				// No.... but we will next time
				shallWeStall = true;
			}

			// Echo data back to clinet
			pout.println (data);

			// Close connection
			m_connection.close();
		}
		catch (IOException ioe) 
		{
			System.err.println ("I/O error");
		}
	}
}


Solution Two : Simplified timeout handling with socket options

A significantly easier solution to handling network timeouts is to set a socket option. Socket options allow programmers greater control over socket communication, and are supported by Java as of JDK1.1. One socket option in particular, SO_TIMEOUT, is extremely useful, because it allows programmers to specify an amount of time that a read operation will block for, before generating anjava.io.InterruptedIOException, which can be easily caught to provide a timeout handler.

We can specify a value for SO_TIMEOUT, by using the setSoTimeout() method. This method is supported by java.net.Socket, java.net.DatagramSocket, and java.net.ServerSocket. This is important, as it means we can handle timeouts in both the client and the server. The setSoTimeout accepts as its sole parameter an int, which represents the number of milliseconds an operation may block for. Settings this value to one thousand will result in timeouts after one second of inactivity, whereas setting SO_TIMEOUT to zero will allow the thread to block indefinitely.

// Set SO_TIMEOUT for five seconds
MyServerSocket.setSoTimeout(5000);

Once the length for the timeout is set, any blocking operation will cause an InterruptedIOException to be thrown. For example, a DatagramSocket that failed to receive packets when the receive() method is called, would throw an exception. This makes it easy to separate our timeout handling code from the task of communicating via the network.

The next example, Listing Four, shows another multi-threaded echo server with timeout support. It limits the number of connections it can support (currently set to two), and rejects further connections. However, if a client fails to send data, a server thread will become blocked, and the number of available connections will be reduced. With larger servers, and hundreds or thousands of connections per hour, blocked threads become a significant problem, and can lead to denial of service. This example shows how to detect a timeout, and to disconnect gracefully. By using socket_options, and catching exceptions, it’s easier to shut down an individual thread.

To test the echo server, you can use the telnet command (available on both Unix/Wintel systems), and connect to port 2000 of your local machine. Type a few characters of text, and then watch what happens after thirty seconds of inactivity. The server will automatically disconnect the telnet client, freeing up the connection for another user.


Listing Four

import java.io.*;
import java.net.*;

/**
  * EchoServer offers an echo service to multiple clients.
  * The echo service is limited to a set number of connections,
  * to prevent server over-load. It also includes timeout handling
  * code to prevent server threads from blocking if a client is
  * stalled.
  */
public class EchoServer extends Thread
{
	/** Connection to client */
	private Socket m_connection;

	/** Number of connections */
	private static int number_of_connections = 0;

	/** Maximum number of connections */
	private static final int max_connections = 2;

	/** Port to bind to */
	private static final int service_port = 2000;

	/** Timeout length */
	private static final int timeout_length = 30000;

	/**
	  * Creates a new instance of EchoServer thread, to
	  * service the specified client connection.
	  *
	  * @param connection	Connection to service
	  */
	public EchoServer (Socket connection)
	{
		// Assign to member variable
		m_connection = connection;

		// Set a timeout of 'timeout_length' milliseconds
		try
		{	
			m_connection.setSoTimeout (timeout_length);
		}
		catch (SocketException se)
		{
			System.err.println ("Unable to set socket option SO_TIMEOUT");
		}

		// Increment number of connections
		number_of_connections++;
	}

	public void run()
	{
		try
		{
			// Get I/O streams
			InputStream  in = m_connection.getInputStream();
			OutputStream out= m_connection.getOutputStream();

			try
			{
				for (;;)
					// Echo data straight back to client
					out.write(in.read());
			}
			catch (InterruptedIOException iioe)
			{
				System.out.println ("Timeout occurred - killing connection");
				m_connection.close();
			}
		}
		catch (IOException ioe)
		{
			// No code required - thread will terminate at end
			// of the run method
		}

		// Decrement the number of connections
		number_of_connections--;
	}

	public static void main(String args[]) throws Exception
	{
		// Bind to a local port
		ServerSocket server = new ServerSocket (service_port);

		for (;;)
		{
			// Accept the next connection
			Socket connection = server.accept();

			// Check to see if maximum reached
			if (number_of_connections > max_connections-1)
			{
				// Kill the connection
				PrintStream pout = new PrintStream (connection.getOutputStream());
				pout.println ("Too many users");
				connection.close();
				continue;
			}
			else
			{
				// Launch a new thread
				new EchoServer(connection).start();
			}
		}
	}
}

Summary

All good network applications will include timeout detection and handling. Whether you’re writing a client, and need to detect a wayward server, or writing a server and need to prevent stalled connections, timeout handling is a critical part of error handling. For those who require backwards compatibility with JDK1.02, timers may be used to detect stalled connections. The most preferable solution though, is to use socket options, and to provide an exception handler for java.io.InterruptedIOException. This reduces the amount of code required to handle timeouts, and makes for a cleaner design.

Gang of Four (GoF) Design Pattern

Gang of Four (GoF) Patterns are 23 main software design patterns providing recurring solutions to common problems in software design. They were developed by  Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, often referred to as the Gang of Four.

We have started this series to explain each of these patterns with a real world example and how to develop and use them in Java.

Creational Design Pattern:

This is all about object creation in a form that they can follow the architecture principle of loose coupling, encapsulation and abstraction. This pattern can provide a great deal of flexibility about which objects are created, how those objects are created, and how they’re initialized. And the most important thing is that the client remains completely unaware of overall object creation process.

 Structural Design Pattern:

This pattern is used to form larger object structures from many different objects.  They show you how to use composition to join different pieces of a system together in a flexible and extensible fashion. This pattern help you guarantee that when one of the parts changes, the entire structure doesn’t need to change. They also show you how to recast pieces that don’t fit into pieces that do fit.

 Behaviour Design Pattern:

This pattern is used to manage relationships, interaction, algorithms and responsibilities between various objects. It also follows the abstraction principle whereby it abstracts the action. This pattern focuses on the interaction between the cooperating objects in a manner that the objects are communicating while maintaining loose coupling.

Creational Pattern Structural Patterns Behavioral Patterns
Abstract Factory Adapter Chain of Responsibility
Builder Bridge Command
Factory Method Composite Interpreter
Prototype Decorator Iterator
Singleton Facade Mediator
Flyweight Memento
Proxy Observer
State
Strategy
Template Method
Visitor

The below diagram provides a clear view of the relationship between the above design patterns mentioned.

Design Pattern Relationship

Types of Creational Design Patterns (as defined by Wikipedia):
Abstract Factory groups object factories that have a common theme.
Builder constructs complex objects by separating construction and representation.
Factory Method creates objects without specifying the exact class to create.
Prototype creates objects by cloning an existing object.
Singleton restricts object creation for a class to only one instance.

Types of Structural Design Pattern (as defined by Wikipedia):
Adapter allows classes with incompatible interfaces to work together by wrapping its own interface around that of an already existing class.
Bridge decouples an abstraction from its implementation so that the two can vary independently.
Composite composes zero-or-more similar objects so that they can be manipulated as one object.
Decorator dynamically adds/overrides behaviour in an existing method of an object.
Facade provides a simplified interface to a large body of code.
Flyweight reduces the cost of creating and manipulating a large number of similar objects.
Proxy provides a placeholder for another object to control access, reduce cost, and reduce complexity.

Types of Behavioral Design Pattern (as defined by Wikipedia):
Command creates objects which encapsulate actions and parameters.
Interpreter implements a specialized language.
Iterator accesses the elements of an object sequentially without exposing its underlying representation.
Mediator allows loose coupling between classes by being the only class that has detailed knowledge of their methods.
Memento provides the ability to restore an object to its previous state (undo).
Observer is a publish/subscribe pattern which allows a number of observer objects to see an event.
State allows an object to alter its behavior when its internal state changes.
Strategy allows one of a family of algorithms to be selected on-the-fly at runtime.
Template method defines the skeleton of an algorithm as an abstract class, allowing its subclasses to provide concrete behavior.
Visitor separates an algorithm from an object structure by moving the hierarchy of methods into one object.

When to use “static” keyword in Java

The static keyword can be used in 3 scenarios

  1. static variables
  2. static methods
  3. static blocks of code.

Lets look at static variables and static methods first.

static variable

  • It is a variable which belongs to the class and not toobject(instance)
  • Static variables are initialized only once , at the start of the execution . These variables will be initialized first, before the initialization of any instance variables
  • A single copy to be shared by all instances of the class
  • A static variable can be accessed directly by the class name and doesn’t need any object
  • Syntax : <class-name>.<variable-name>

static method

  • It is a method which belongs to the class and not to the object(instance)
  • A static method can access only static data. It can not access non-static data (instance variables)
  • A static method can call only other static methods and can not call a non-static method from it.
  • A static method can be accessed directly by the class name and doesn’t need any object
  • Syntax : <class-name>.<method-name>
  • A static method cannot refer to “this” or “super” keywords in anyway

Side Note:

  • main method is static , since it must be be accessible for an application to run , before any instantiation takes place.

Lets learn the nuances of the static keywords by doing some excercises!

Assignment: To Learn working of static variables & methods

Step 1) Copy the following code into a editor

public class Demo{
 public static void main(String args[]){
 Student s1 = new Student();
 s1.showData();
 Student s2 = new Student();
 s2.showData();
 //Student.b++;
 //s1.showData();
 }
}

class Student {
int a; //initialized to zero
static int b; //initialized to zero only when class is loaded not for each object created.

 Student(){
 //Constructor incrementing static variable b
 b++;
 }

 public void showData(){
 System.out.println("Value of a = "+a);
 System.out.println("Value of b = "+b);
 }
//public static void increment(){
//a++;
//}

}

This code is editable. Click Run to Compile + Execute

Step 2) Save & Compile the code. Run the code as, java Demo.

Step 3) Expected output show below

java-static-variable

Following diagram shows , how reference variables & objects are created and static variables are accessed by the different instances.

java-static

Step 4) It is possible to access a static variable from outside the class using the syntaxClassName.Variable_Name. Uncomment line # 7 & 8 . Save , Compile & Run . Observe the output.

Step 5) Uncomment line 25,26 & 27 . Save , Compile & Run.

Step 6) Error = ? This is because it is not possible to access instance variable “a” from static method “increment“.

static block

The static block, is a block of statement inside a Java class that will be executed when a class is first loaded in to the JVM

class Test{
  static{
  //code goes here
  }
}

A static block helps to initialize the static data members, just like constructors help to initialize instance members

Why Johnny Can’t Write Multithreaded Programs

Programming for multiple threads is not fundamentally different from writing an event-oriented GUI application or even a straight up sequential application. The important lessons of encapsulation, separation of concerns, loose coupling, etc. all apply. But developers get into trouble with multiple threads when they don’t apply those lessons; instead they try to apply the mostly-irrelevant bits of information they learned about threads and synchronization primitives from introductory multithreading texts.

Some people, when confronted with a problem, think, “I know, I’ll use regular expressions.” Now they have two problems. –Jaimie Zawinski

Some people, when confronted with a problem, think, “I know, I’ll use threads!” Now they have 10 problems. –Bill Schindler

Too many programmers writing multithreaded programs are like Mickey Mouse inThe Sorcerer’s Apprentice. They learn to create a bunch of threads and get them mostly working, but then the threads go completely out of control and the programmer doesn’t know what to do.

Unlike Mickey, those programmers don’t have the luxury of a kindly master wizard who can wave his magic wand and restore sanity. Instead, the programmer resorts to all manner of ugly hacks in an attempt to fix problems as they pop up. The result is invariably an overly complicated, restrictive, fragile, and unreliable application that’s prone to deadlocks and other multithreading hazards. Not to mention unexplained crashes, poor performance, and incomplete or incorrect results.

You’ve probably wondered why that is. Perhaps you’ve accepted the common fallacy that “Multithreading is hard.” It’s not. If a multithreaded program is unreliable it’s most likely due to the same reasons that single-threaded programs fail: The programmer didn’t follow basic, well known development practices. Multithreaded programs seem harder or more complex to write because two or more concurrent threads working incorrectly make a much bigger mess a whole lot faster than a single thread can.

The “multithreading is hard” fallacy is propagated by programmers who, out of their depth in a single-threaded world, jump feet first into multithreading – and drown. Rather than re-examine their development practices or preconceived notions, they stubbornly try to “fix” things, and use the “multithreading is hard” excuse to justify their unreliable programs and missed delivery dates.

Note that I’m talking here about the majority of programs that use multithreading. There are difficult multithreading scenarios, just as there are difficult scenarios in the single-threaded world. But those are relatively rare. For the majority of what most programmers do, the problems just aren’t that complicated. We move data around, transform it, perhaps do some calculations from time to time, and finally store the results in a database or display them on the screen.

Upgrading a typical single-threaded program so that it uses multiple threads isn’t (or shouldn’t be) very difficult. It becomes difficult for two reasons:

  • Developers fail to apply simple, well known development practices; and
  • Most of what they were taught in introductory multithreading materials is technically correct but completely irrelevant to the problems at hand.

The most important concepts in programming are universal; they apply equally to single-threaded and multithreaded programs. Programmers who drown in a sea of threads haven’t learned the important lessons from writing single-threaded programs. I know this because they make the same fundamental mistakes in their multithreaded programs as they do in their single-threaded programs.

Probably the most important lesson to be learned from the past 60 years of software development is that global mutable state is bad. Really bad. Programs that depend on global mutable state are harder to reason about and generally less reliable, because there are too many possible ways for the state to change. There is a huge amount of research to back up that generalization, and countless design patterns whose primary purpose is to implement some type of data hiding. The best thing you can do to make your programs easier to reason about is to eliminate as much global mutable state as possible.

In a single-threaded sequential program, the likelihood of data being mangled is proportional to the number of components that can modify that data.

It’s usually not possible to completely eliminate global state, but we developers have very effective tools for strictly controlling which parts of a program can modify it. In addition, we’ve learned to create restrictive API layers around primitive data structures so that we also control how those data structures are changed.

The problems of global mutable state became more apparent in the late ’80s and early ’90s with the widespread use of event-oriented programming. Programs no longer start at the beginning and follow a single predictable path to conclusion. Instead, the program has an initial state and events occur at unpredictable times in an unpredictable order. The code is still single-threaded, but it’s asynchronous. The likelihood of data being mangled increases because the order in which events can occur is a factor. It’s not uncommon to find that if event A occurs before event B, then everything’s fine. But if A follows B, especially if event C occurs in between, then the data is mangled beyond recognition.

Adding concurrent threads complicates the problem even further because multiple methods can manipulate the global state at the same time. It becomes impossible to reason about how the global state is changing. Not only is the order of events unpredictable, but multiple threads of execution can be updating the state at the same time. At least in the asynchronous case you can guarantee that one event will complete its processing before any other event can start. In short, it is possible to say with certainty what the global state will be at the end of an event’s processing. With multiple threads it’s impossible in the general case to say which events will execute concurrently, and it’s therefore impossible to say what the global state is at any given point in time.

A multithreaded program with extensive global mutable state is one of the best demonstrations of the Heisenberg uncertainty principle I know of. It’s impossible to examine the state without changing the program’s behavior.

When I launch into my prepared rant about global mutable state (a somewhat expanded version of the last few paragraphs), programmers roll their eyes and tell me that they already know that. If they do know that, their programs don’t show it. The programs are filled with global mutable state, and the programmers wonder why their programs don’t work.

Not surprisingly, the most important part of creating a multithreaded program is design: figuring out what the program has to do, designing independent modules to perform those functions, clearly identifying what data each module needs, and defining the communications paths between modules. [Also: designing the project team’s t-shirt. Some things take priority. –Ed.] The fundamental process is no different from designing a single-threaded program. The key to success is, as with a single-threaded program, limiting interactions between the modules. If you eliminate shared mutable state, then data sharing problems are impossible.

You might think that you can’t afford the time to design your application so that it doesn’t use global state. In my opinion you can’t afford not to. Trying to manage global mutable state kills more multithreaded programs than anything else. The more you have to manage, the more likely it is that your program will crash and burn.

Most real world programs require some shared state that can be changed, and that’s where programmers most often get into trouble. Seeing the need for sharing state, programmers often reach into their multithreading toolbox and pull out the only tool they have: the all-purpose lock (critical section, mutex, or whatever it’s called in their particular language). They figure, I suppose, that they can eliminate the data sharing problems with mutual exclusion.

The number of problems you can encounter with a single lock is astounding. There are race conditions to think about, gating problems with an overly broad lock, and fairness issues, just to name a few. If you have multiple locks, especially nested locks, you have to worry about deadlock, livelock, lock convoys, and other concurrency hazards in addition to the problems associated with a single lock. Things get complicated in a hurry.

When writing or reviewing application code, I have a simple rule of thumb that rarely fails: If you used a lock, you probably did something wrong.

That statement can be taken two ways:

  1. If you need a lock, then you probably have global mutable state that has to be protected against concurrent updates. The existence of global mutable state indicates a flaw in the application’s design, which you should review and change.
  2. Locks are difficult to use correctly, and locking bugs can be incredibly difficult to isolate. The likelihood of there being an error in the way you used the lock is very high. If I see a lock, especially in a program that exhibits unusual behavior, the first place I look for the failure is the code that depends on the lock being used correctly. And that’s where I usually find it.

Both of those interpretations apply.

Multithreading isn’t hard. Properly using synchronization primitives, though, is really, really, hard. You probably aren’t qualified to use even a single lock properly. Locks and other synchronization primitives are systems level constructs. People who know a lot more about multithreading use those constructs to build concurrent data structures and higher level synchronization constructs that mere application programmers like you and I use in our programs. Application programmers should use the low-level synchronization primitives about as often as they make direct device driver calls: almost never.

Trying to solve a data sharing problem with locks is like trying to put out a fire by throwing liquid oxygen on it. As with fires, prevention is the best solution. If you eliminate shared state, you have no reason to misuse those synchronization primitives.

Most of what you know about multithreading is irrelevant

Introductory multithreading materials explain what threads are. Then they launch into discussions of how to make those threads work together in various ways, such as controlling access to shared data with locks and semaphores, and perhaps controlling when things happen with events. There’s detailed discussion of condition variables, memory barriers, critical sections, mutexes, volatile fields, and atomic operations. You’re given examples of how to use those low level constructs to do all manner of systems level things. By the time a programmer is halfway through that material, she thinks she knows how to use those primitives in her applications. After all, if you understand how to use something at the systems level, using it at the application level should be trivial, right?

This is like teaching a teenager how to build an internal combustion engine from discrete parts and then, without the benefit of any driving instruction, setting him behind the wheel of a car and turning him loose on the roads. The teenager understands how the car works internally, but he has no idea how to drive it from point A to point B.

Knowing how threads work at the systems level is mostly irrelevant to understanding how to use them in an application program. I’m not saying that programmers shouldn’t know how things work under the hood, just that they shouldn’t expect that knowledge to be directly applicable to the design or implementation of a business application. After all, knowing the details of the intake, compression, combustion, and exhaust cycle doesn’t help you in getting from home to the grocery store and back.

Introductory multithreading textbooks (and computer science courses) shouldn’t be teaching those low level constructs. Rather, they should concentrate on common classes of problems and show developers how to use higher level constructs to solve those problems. For example, a large number of business applications are in concept extremely simple programs: They read data from one or more input devices, apply some arbitrarily complex processing to that data (perhaps querying some other stored data in the process), and then output the results.

These programs very often fit nicely into a producer-consumer model with three threads:

  • The input thread reads data and places it on the input queue.
  • The processing thread reads records from the input queue, processes them, and puts them on the output queue.
  • The output thread reads records from the output queue and stores them.

The three threads operate independently and communicate through the queues. Although technically those queues are shared state, in practice they are communications channels with their own internal, synchronization. The queues support multiple producers and consumers, all adding or removing items concurrently.

Because the input, processing, and output are each isolated, it’s easy to change their implementations without affecting the rest of the program. As long as the queue data types remain unchanged, the individual pieces can be refactored at will. In addition, because the queues handle an arbitrary number of producers and consumers, adding more producers or consumers is no problem. There could be a dozen input threads all writing to the same queue, or multiple processing threads removing input items and crunching the data. Within the confines of a single computer, this model scales well.

Perhaps most importantly, modern programming languages and libraries make it easy to create a producer-consumer application. In .NET you have concurrent collections and TPL Dataflow. Java has the Executer service, BlockingQueue, and other classes in the java.util.concurrent namespace. In C++ you have the Boost threading library and Intel’s Thread Building Blocks. Microsoft introduced its Asynchronous Agents with Visual Studio 2013. Similar libraries are available for Python, Javascript, Ruby, PHP, and for all I know many other languages. You can create a producer-consumer application with any of those packages without ever having to use a lock, semaphore, condition variable, or any other synchronization primitive.

Granted, those libraries likely make liberal use of many different synchronization primitives. That’s okay. Those libraries were written by people who know multithreading a whole lot better than does your average application programmer. Using a library like that is no different from using a language’s runtime library, or writing in a high level language rather than Assembly language.

The producer-consumer model is just one example. The libraries I mentioned above include classes with which you can implement many common multithreading design patterns without once dipping into low-level multithreading. It’s possible to create extensive multithreading applications without knowing a thing about how threads and synchronization work under the hood.

Use the libraries

Writing programs that use multiple threads is not fundamentally different from writing single-threaded synchronous programs. The important lessons of encapsulation and data hiding are universal, and become even more important when multiple concurrent threads are involved. If you ignore those important lessons, then no amount of low level threading knowledge can save you.

Programmers today have plenty to worry about at the application level without having to think about systems-level things. As applications become more involved, we increasingly hide complexity behind API layers. We’ve been doing this for decades. One could make a good argument that hiding complexity from programmers is the primary reason they are able to create complex applications. After all, don’t we already hide the complexities of the file system, the UI message loop, low-level communication protocols, etc.?

Multithreading concepts should be no different. The majority of multithreading scenarios business programmers are likely encounter are well known and implemented in libraries that hide the bewildering complexity of dealing with concurrency. We should use those libraries in the same way that we use libraries of user interface controls, communications protocols, and the countless other tools that simplify our jobs. Leave low level multithreading to the people who know what they’re doing: the ones who write the libraries we use to build real programs.

Jim Mischel is a developer with Professional Datasolutions, Inc., a leading provider of software, hardware, and professional services to convenience retailers and wholesale petroleum marketers. When he’s not banging out code or writing about his experiences, he’s probably putting in miles on his bike or working on his latest wood carving project. Keep up with Jim on his blog.

Thread Interference

Consider a simple class called Counter

class Counter {
    private int c = 0;

    public void increment() {
        c++;
    }

    public void decrement() {
        c--;
    }

    public int value() {
        return c;
    }

}

Counter is designed so that each invocation of increment will add 1 to c, and each invocation of decrement will subtract 1 from c. However, if a Counter object is referenced from multiple threads, interference between threads may prevent this from happening as expected.

Interference happens when two operations, running in different threads, but acting on the same data, interleave. This means that the two operations consist of multiple steps, and the sequences of steps overlap.

It might not seem possible for operations on instances of Counter to interleave, since both operations on c are single, simple statements. However, even simple statements can translate to multiple steps by the virtual machine. We won’t examine the specific steps the virtual machine takes — it is enough to know that the single expression c++ can be decomposed into three steps:

  1. Retrieve the current value of c.
  2. Increment the retrieved value by 1.
  3. Store the incremented value back in c.

The expression c-- can be decomposed the same way, except that the second step decrements instead of increments.

Suppose Thread A invokes increment at about the same time Thread B invokes decrement. If the initial value of c is 0, their interleaved actions might follow this sequence:

  1. Thread A: Retrieve c.
  2. Thread B: Retrieve c.
  3. Thread A: Increment retrieved value; result is 1.
  4. Thread B: Decrement retrieved value; result is -1.
  5. Thread A: Store result in c; c is now 1.
  6. Thread B: Store result in c; c is now -1.

Thread A’s result is lost, overwritten by Thread B. This particular interleaving is only one possibility. Under different circumstances it might be Thread B’s result that gets lost, or there could be no error at all. Because they are unpredictable, thread interference bugs can be difficult to detect and fix.

Design Pattern – Singleton Pattern

Singleton pattern is one of the simplest design patterns in Java. This type of design pattern comes under creational pattern as this pattern provides one of the best ways to create an object.

This pattern involves a single class which is responsible to create an object while making sure that only single object gets created. This class provides a way to access its only object which can be accessed directly without need to instantiate the object of the class.

Implementation

We’re going to create a SingleObject class. SingleObject class have its constructor as private and have a static instance of itself.

SingleObject class provides a static method to get its static instance to outside world. SingletonPatternDemo, our demo class will use SingleObjectclass to get a SingleObject object.

Singleton Pattern UML Diagram

Step 1

Create a Singleton Class.

SingleObject.java

public class SingleObject {

   //create an object of SingleObject
   private static SingleObject instance = new SingleObject();

   //make the constructor private so that this class cannot be
   //instantiated
   private SingleObject(){}

   //Get the only object available
   public static SingleObject getInstance(){
      return instance;
   }

   public void showMessage(){
      System.out.println("Hello World!");
   }
}

Step 2

Get the only object from the singleton class.

SingletonPatternDemo.java

public class SingletonPatternDemo {
   public static void main(String[] args) {

      //illegal construct
      //Compile Time Error: The constructor SingleObject() is not visible
      //SingleObject object = new SingleObject();

      //Get the only object available
      SingleObject object = SingleObject.getInstance();

      //show the message
      object.showMessage();
   }
}

Step 3

Verify the output.

Hello World!

Wifi Direct:群组问题

1.在 4.2 以上版本,如果直连配对成功过,设置里会显示已保存的群组,以后这两台手机连接就无需确认,可以直接连上,不会弹出对话框让用户选择同意或是拒绝。4.0 里还没有群组这个东西。

2.4.2版本的 WifiP2pSettings 源码中,连接成功后,会默认自动记下这个群组。

在 WifiPpManager 中,当有两设备连成功构成组后:

1
2
3
4
5
6
case WifiP2pManager.RESPONSE_PERSISTENT_GROUP_INFO:
    WifiP2pGroupList groups = (WifiP2pGroupList) message.obj;
    if (listener != null) {
        ((PersistentGroupInfoListener) listener).onPersistentGroupInfoAvailable(groups);
    }
break;

而 onPersistentGroupInfoAvailable(groups) 是这个类中的内部接口中定义的方法,在 WifiP2pSettings 中实现了这个接口,重写了方法

1
2
3
4
5
6
7
public void onPersistentGroupInfoAvailable(WifiP2pGroupList groups) {
    mPersistentGroup.removeAll();
    for (WifiP2pGroup group: groups.getGroupList()) {
        if (DBG)     Log.d(TAG, " group " + group);
        mPersistentGroup.addPreference(new WifiP2pPersistentGroup(getActivity(), group));
    }
}

得到组的列表,然后将组添加到界面上

3.群组封装的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class WifiP2pPersistentGroup extends Preference {
    public WifiP2pGroup mGroup;
    public WifiP2pPersistentGroup(Context context, WifiP2pGroup group) {
        super(context);
        mGroup = group;
    }
    @Override
    protected void onBindView(View view) {
        setTitle(mGroup.getNetworkName());
        super.onBindView(view);
    }
    int getNetworkId() {
        return mGroup.getNetworkId();
    }
    String getGroupName() {
        return mGroup.getNetworkName();
    }
}
// 如果点击了群组,弹出对话框问是否要删除群组
else if (preference instanceof WifiP2pPersistentGroup) {
    mSelectedGroup = (WifiP2pPersistentGroup) preference;
    showDialog(DIALOG_DELETE_GROUP);
}
else if (id == DIALOG_DELETE_GROUP) {
    int stringId = R.string.wifi_p2p_delete_group_message;
    AlertDialog dialog = new AlertDialog.Builder(getActivity())
        .setMessage(getActivity().getString(stringId))
        .setPositiveButton(getActivity().getString(R.string.dlg_ok), mDeleteGroupListener)
        .setNegativeButton(getActivity().getString(R.string.dlg_cancel), null)
        .create();
    return dialog;
}

4.删除群组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//delete persistent group dialog listener
mDeleteGroupListener = new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
    if (which == DialogInterface.BUTTON_POSITIVE) {
        if (mWifiP2pManager != null) {
            mWifiP2pManager.deletePersistentGroup(mChannel,
                mSelectedGroup.getNetworkId(),
                new WifiP2pManager.ActionListener() {
                    public void onSuccess() {
                        if (DBG) Log.d(TAG, " delete group success");
                    }
                    public void onFailure(int reason) {
                        if (DBG) Log.d(TAG, " delete group fail " + reason);
                    }
                });
            }
        }
    }
};

5.manager.requestGroupInfo(channel, activity) 会调用 GroupInfoListener 接口里的 onGroupInfoAvailable 方法,得到组的信息。GroupInfoListener 这个接口要实现 onGroupInfoAvailable(WifiP2pGroup group) 方法,group 里包含一个 Group Owner 和多个 Group Client 的信息。

Wifi Direct:功能测试

1.WiFi 直连中收到 WIFI_P2P_STATE_CHANGED_ACTION 广播时,更改直连状态,根据状态不同执行相应操作。如果 WiFi 未开启,要跳到设置界面去设置,本来想如果设置返回还要判断执行,所以放到 onResum 方法里执行,但这样有问题,这个界面还可能跳到其它界面,状态可能没改变,而且 onResume 比广播接收者要调用的方法执行的更早,所以 onResume 里用到的 isWifiP2pEnabled 并不是最新的。所以后来放在更改状态之后执行,这样只要更改状态就执行。

        广播接收者收到广播调用Activity中的方法,设置状态后,把自己想要紧接着做的封装到一个方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public void setIsWifiP2pEnabled(boolean isWifiP2pEnabled) {
    this.isWifiP2pEnabled = isWifiP2pEnabled;
    // 状态变化了,调用这个方法
    testAndDiscover();
}
// 看WiFi功能是否开启,若开启,去发现设备
private void testAndDiscover() {
 
    if(!isWifiP2pEnabled) {
        AlertDialog.Builder builder = new Builder(this);
        builder.setTitle("提示")
        .setMessage("请先确认您的设备支持WiFi直连功能。如果支持,请先在设置中开启WiFi")
        .setPositiveButton("去设置"new DialogInterface.OnClickListener() {
 
            @Override
            public void onClick(DialogInterface dialog, int which) {
                startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
            }
        })
        .setNegativeButton("不弄了"new DialogInterface.OnClickListener() {
 
            @Override
            public void onClick(DialogInterface dialog, int which) {
 
            }
        }).show();
    else // 如果wifi直连功能支持并已开启
        WifiDirectUtil.discoverPeers(DeviceListActivity.this, manager, channel);
    }
}

2.广播接收者里收到的 WIFI_P2P_THIS_DEVICE_CHANGED_ACTION 这个广播是更新自己的状态

1
2
3
4
5
if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
    // 更新自己的设备状态
    activity.updateThisDevice((WifiP2pDevice) intent
            .getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE));
}
        收到广播的意图intent中保存了自己这个设备的信息,所以通过(WifiP2pDevice) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE 来得到自己这台设备 WifiP2pDevice 对象。
        更新自己的设备状态
1
2
3
4
5
6
public void updateThisDevice(WifiP2pDevice device) {
    TextView myName = (TextView) findViewById(R.id.my_name);
    TextView myStatus  = (TextView) findViewById(R.id.my_status);
    myName.setText(device.deviceName);
    myStatus.setText(Util.getDeviceStatus(device.status));
}

其中 device.status 是int型值,所以要转变为对应文字,这样看着有意义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static String getDeviceStatus(int deviceStatus) {
    switch (deviceStatus) {
    case WifiP2pDevice.AVAILABLE:
        return "Available";
    case WifiP2pDevice.INVITED:
        return "Invited";
    case WifiP2pDevice.CONNECTED:
        return "Connected";
    case WifiP2pDevice.FAILED:
        return "Failed";
    case WifiP2pDevice.UNAVAILABLE:
        return "Unavailable";
    default:
        return "Unknown";
    }
}

3.原来 discoverPeers,requestPeers 之类的方法都是放在Activity里,但如果作为一个库供其它程序调用的话要把这些方法提取出来放到一个工具类里。比如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
   * 去发现设备
   * @param context
   * @param manager
   * @param channel
   */
public static void discoverPeers(final Context context, WifiP2pManager manager, Channel channel) {
    Log.i(TAG, "discoverPeers");
    manager.discoverPeers(channel, new ActionListener() {
 
        @Override
        public void onSuccess() {
            // 成功后,会收到对应广播
        }
 
        @Override
        public void onFailure(int reason) {
            Toast.makeText(context, "搜索设备失败,错误代码:" + reason,
                    Toast.LENGTH_SHORT).show();
        }
    });
}
 
/**
   * 更新自己这台设备的状态
   * @param activity
   * @param device
   */
public static void updateThisDevice(Activity activity, WifiP2pDevice device) {
    Log.i(TAG, "updateThisDevice");
    TextView myName = (TextView) activity.findViewById(R.id.my_name);
    TextView myStatus  = (TextView) activity.findViewById(R.id.my_status);
    myName.setText(device.deviceName);
    myStatus.setText(getDeviceStatus(device.status));
}
        这样在 Activity 和 BroadcastReceiver 中只要调用这些方法,并传入对应参数即可。
        在广播接收者里收到 WIFI_P2P_PEERS_CHANGED_ACTION 这个广播时,要调用 WifiP2pManager 的requestPeers 方法,第二个参数是 PeerListListener 对象,会自动回调里面的 onPeersAvailable 方法。原来是让设备列表的适配器直接实现 PeerListListener,但这样就写死了,所以考虑将这个 requestPeers 方法也提取到工具类里。
        在 onPeersAvailable 方法里得到更新的设备列表,应该去更新适配器的数据并刷新。原来是这样的
1
2
3
4
5
6
7
8
9
10
11
@Override
public void onPeersAvailable(WifiP2pDeviceList peerList) {
    // peers 就是适配器中用到的那个设备列表集合    
    peers.clear();
    peers.addAll(peerList.getDeviceList());
 
    notifyDataSetChanged(); // 刷新适配器
    if (peers.size() == 0) {
        return;
    }
}

但现在将 PeerListListener 和适配器分离,所以考虑得到最新的列表后去通过方法调用去更改适配器中内容,然后再刷新,所以要在适配器类中添加一个方法,去设置它自己的那个 List 集合,但用户开始不知道一定要有这方法,所以写一个接口

1
2
3
4
5
6
7
8
public interface BaseDeviceAdapter {
    /**
       * 更新适配器中的设备列表那个List集合。并刷新适配器内容
       * @param peers
       */
    public void updateDeviceList(List<WifiP2pDevice> peers);
}

这样自己写的 DeviceAdapter 实现接口,重写这个方法

1
2
3
4
5
6
// 更新peers并刷新适配器
@Override
public void updateDeviceList(List<WifiP2pDevice> peers) {
    this.peers = peers;
    notifyDataSetChanged();
}

在工具类里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
   * 查找设备
   * @param manager
   * @param channel
   * @param adapter 要更新内容的适配器,类型是自己定义的那个接口
   */
public static void requestPeers(WifiP2pManager manager,  Channel channel, final BaseDeviceAdapter adapter) {
    Log.i(TAG, "requestPeers");
    manager.requestPeers(channel, new PeerListListener() {
 
        @Override
        public void onPeersAvailable(WifiP2pDeviceList peerList) {
            List<WifiP2pDevice> peers = new ArrayList<WifiP2pDevice>();
            peers.clear();
            peers.addAll(peerList.getDeviceList());
 
            // 更新适配器中内容。利用参数传递的那个接口调用
            adapter.updateDeviceList(peers);
            if (peers.size() == 0) {
                return;
            }
        }
    });
}

4.连接一台设备,知道的是WifiP2pDevice,WifiP2pManager 真正去 connect 需要的 WifiP2pConfig 信息通过 WifiP2pDevice 来设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void connect(final Context context, WifiP2pManager manager,
    Channel channel, WifiP2pDevice device) {
    WifiP2pConfig config = new WifiP2pConfig();
    config.deviceAddress = device.deviceAddress;
    config.wps.setup = WpsInfo.PBC;
 
    manager.connect(channel, config, new ActionListener() {
        @Override
        public void onSuccess() {
            // WiFiDirectBroadcastReceiver will notify us. Ignore for now.
        }
 
        @Override
        public void onFailure(int reason) {
            Toast.makeText(context, "连接失败,请重试", Toast.LENGTH_SHORT).show();
        }
    });
}

5.广播接收者收到这个广播 WIFI_P2P_CONNECTION_CHANGED_ACTION 表示连接状态改变了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
if (manager == null) {
    return;
}
 
NetworkInfo networkInfo = (NetworkInfo) intent
                    .getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
 
if (networkInfo.isConnected()) { // 成功连接上
    Log.i(TAG, "收到广播:连接成功");
    WifiDirectUtil.requestConnectionInfo(manager, channel);
else {
    // 不管哪一方主动断开连接,这里都会收到广播,在这里去重置数据
    // 比如清空一些数据,或者重新 discoverPeers 显示到界面上
    activity.resetData();
}
        
// 在Activity中,如果直连断了,重新查找设备
public void resetData() {
    WifiDirectUtil.discoverPeers(DeviceListActivity.this, manager, channel);
}
        而在 Activity 中的 onCreate 方法中每次进入都调用 adapter.clearPeers() 先清空适配器中数据,不然上一次的数据不清空会影响下一次的界面显示内容。
        在适配器中
1
2
3
4
public void clearPeers() {
    peers.clear();
    notifyDataSetChanged();
}

在 onDestory 中断开连接,如果原来是连接的,断开成功,如果原来就是断开的,断开失败,反正没影响。