Home > Articles > Programming > Java

Adding Multithreading Capability to Your Java Applications

Cay Horstmann shows you how to add multithreading capability to your Java applications and applets in this sample chapter from Core Java 2, Volume II: Advanced Features, 5th edition.
This sample chapter is excerpted from Core Java 2, Volume II: Advanced Features, 5th edition, by Cay Horstmann.
This chapter is from the book
  • What Are Threads?
  • Interrupting Threads
  • Thread Properties
  • Thread Priorities
  • Selfish Threads
  • Synchronization
  • Deadlocks
  • User Interface Programming with Threads
  • Using Pipes for Communication between Threads

You are probably familiar with multitasking: the ability to have more than one program working at what seems like the same time. For example, you can print while editing or sending a fax. Of course, unless you have a multiple-processor machine, what is really going on is that the operating system is doling out resources to each program, giving the impression of parallel activity. This resource distribution is possible because while you may think you are keeping the computer busy by, for example, entering data, most of the CPU's time will be idle. (A fast typist takes around 1/20 of a second per character typed, after all, which is a huge time interval for a computer.)

Multitasking can be done in two ways, depending on whether the operating system interrupts programs without consulting with them first, or whether pro-grams are only interrupted when they are willing to yield control. The former is called preemptive multitasking; the latter is called cooperative (or, simply, nonpreemptive) multitasking. Windows 3.1 and Mac OS 9 are cooperative multitasking systems, and UNIX/Linux, Windows NT (and Windows 95 for 32-bit programs), and OS X are preemptive. (Although harder to implement, preemptive multitasking is much more effective. With cooperative multitasking, a badly behaved program can hog everything.)

Multithreaded programs extend the idea of multitasking by taking it one level lower: individual programs will appear to do multiple tasks at the same time. Each task is usually called a thread—which is short for thread of control. Programs that can run more than one thread at once are said to be multithreaded. Think of each thread as running in a separate context: contexts make it seem as though each thread has its own CPU—with registers, memory, and its own code.

So, what is the difference between multiple processes and multiple threads? The essential difference is that while each process has a complete set of its own variables, threads share the same data. This sounds somewhat risky, and indeed it can be, as you will see later in this chapter. But it takes much less overhead to create and destroy individual threads than it does to launch new processes, which is why all modern operating systems support multithreading. Moreover, inter-process communication is much slower and more restrictive than communication between threads.

Multithreading is extremely useful in practice. For example, a browser should be able to simultaneously download multiple images. An email program should let you read your email while it is downloading new messages. The Java programming language itself uses a thread to do garbage collection in the background—thus saving you the trouble of managing memory! Graphical user interface (GUI) programs have a separate thread for gathering user interface events from the host operating environment. This chapter shows you how to add multithreading capability to your Java applications and applets.

Fair warning: multithreading can get very complex. In this chapter, we present all of the tools that the Java programming language provides for thread programming. We explain their use and limitations and give some simple but typical examples. However, for more intricate situations, we suggest that you turn to a more advanced reference, such as Concurrent Programming in Java by Doug Lea [Addison-Wesley 1999].

NOTE

In many programming languages, you have to use an external thread package to do multithreaded programming. The Java programming language builds in multithreading, which makes your job much easier.

What Are Threads?

Let us start by looking at a program that does not use multiple threads and that, as a consequence, makes it difficult for the user to perform several tasks with that program. After we dissect it, we will then show you how easy it is to have this program run separate threads. This program animates a bouncing ball by continually moving the ball, finding out if it bounces against a wall, and then redrawing it. (See Figure 1–1.)

As soon as you click on the "Start" button, the program launches a ball from the upper-left corner of the screen and the ball begins bouncing. The handler of the "Start" button calls the addBall method:

  public void addBall()
  {
   try
   {
     Ball b = new Ball(canvas);
     canvas.add(b);
     for (int i = 1; i <= 1000; i++)
     {
      b.move();
      Thread.sleep(5);
     }
   }
   catch (InterruptedException exception)
   {          
   }
 }

That method contains a loop running through 1,000 moves. Each call to move moves the ball by a small amount, adjusts the direction if it bounces against a wall, and then redraws the canvas. The static sleep method of the Thread class pauses for 5 milliseconds.

Figure 1–1: Using a thread to animate a bouncing ball

The call to Thread.sleep does not create a new thread—sleep is a static method of the Thread class that temporarily stops the activity of the current thread.

The sleep method can throw an InterruptedException. We will discuss this exception and its proper handling later. For now, we simply terminate the bouncing if this exception occurs.

If you run the program, the ball bounces around nicely, but it completely takes over the application. If you become tired of the bouncing ball before it has finished its 1,000 bounces and click on the "Close" button, the ball continues bouncing anyway. You cannot interact with the program until the ball has finished bouncing.

NOTE

If you carefully look over the code at the end of this section, you will notice the call

canvas.paint(canvas.getGraphics()) 

inside the move method of the Ball class. That is pretty strange—normally, you'd call repaint and let the AWT worry about getting the graphics context and doing the painting. But if you try to call canvas.repaint() in this program, you'll find out that the canvas is never repainted since the addBall method has completely taken over all processing. In the next program, where we use a separate thread to compute the ball position, we'll again use the familiar repaint.

Obviously, the behavior of this program is rather poor. You would not want the programs that you use behaving in this way when you ask them to do a time-consuming job. After all, when you are reading data over a network connection, it is all too common to be stuck in a task that you would really like to interrupt. For example, suppose you download a large image and decide, after seeing a piece of it, that you do not need or want to see the rest; you certainly would like to be able to click on a "Stop" or "Back" button to interrupt the loading process. In the next section, we will show you how to keep the user in control by running crucial parts of the code in a separate thread.

Example 1–1 is the entire code for the program.

Example 1–1: Bounce.java

	1.	import java.awt.*;
	2.	import java.awt.event.*;
	3.	import java.awt.geom.*;
	4.	import java.util.*;
	5.	import javax.swing.*;
	6.	
	7.	/**
	8.	  Shows an animated bouncing ball.
	9.	*/
	10.	public class Bounce
	11.	{
	12.	  public static void main(String[] args)
	13.	  {
	14.	   JFrame frame = new BounceFrame();
	15.	   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	16.	   frame.show();
	17.	  }
	18.	}
	19.	
	20.	/**
	21.	  The frame with canvas and buttons.
	22.	*/
	23.	class BounceFrame extends JFrame
	24.	{
	25.	  /**
	26.	   Constructs the frame with the canvas for showing the
	27.	   bouncing ball and Start and Close buttons
	28.	  */
	29.	  public BounceFrame()
	30.	  {
	31.	   setSize(WIDTH, HEIGHT);
	32.	   setTitle("Bounce");
	33.	
	34.	   Container contentPane = getContentPane();
	35.	   canvas = new BallCanvas();
	36.	   contentPane.add(canvas, BorderLayout.CENTER);
	37.	   JPanel buttonPanel = new JPanel();
	38.	   addButton(buttonPanel, "Start",
	39.	     new ActionListener()
	40.	      { 
	41.	        public void actionPerformed(ActionEvent evt)
	42.	        {
	43.	         addBall();
	44.	        }
	45.	      });
	46.	
	47.	   addButton(buttonPanel, "Close",
	48.	     new ActionListener()
	49.	      {
	50.	        public void actionPerformed(ActionEvent evt)
	51.	        {
	52.	         System.exit(0);
	53.	        }
	54.	      });
	55.	   contentPane.add(buttonPanel, BorderLayout.SOUTH);
	56.	  }
	57.	
	58.	  /**
	59.	   Adds a button to a container.
	60.	   @param c the container
	61.	   @param title the button title
	62.	   @param listener the action listener for the button
	63.	  */
	64.	  public void addButton(Container c, String title,
	65.	   ActionListener listener)
	66.	  {
	67.	   JButton button = new JButton(title);
	68.	   c.add(button);
	69.	   button.addActionListener(listener);
	70.	  }
	71.	
	72.	  /**
	73.	   Adds a bouncing ball to the canvas and makes 
	74.	   it bounce 1,000 times.
	75.	  */
	76.	  public void addBall()
	77.	  {
	78.	   try
	79.	   {
	80.	     Ball b = new Ball(canvas);
	81.	     canvas.add(b);
	82.	
	83.	     for (int i = 1; i <= 1000; i++)
	84.	     {
	85.	      b.move();
	86.	      Thread.sleep(5);
	87.	     }
	88.	   }
	89.	   catch (InterruptedException exception)
	90.	   {          
	91.	   }
	92.	  }
	93.	
	94.	  private BallCanvas canvas;
	95.	  public static final int WIDTH = 450;
	96.	  public static final int HEIGHT = 350; 
	97.	}
	98.	
	99.	/**
	100.	  The canvas that draws the balls.
	101.	*/
	102.	class BallCanvas extends JPanel
	103.	{
	104.	  /**
	105.	   Add a ball to the canvas.
	106.	   @param b the ball to add
	107.	  */
	108.	  public void add(Ball b)
	109.	  {
	110.	   balls.add(b);
	111.	  }
	112.	
	113.	  public void paintComponent(Graphics g)
	114.	  {
	115.	   super.paintComponent(g);
	116.	   Graphics2D g2 = (Graphics2D)g;
	117.	   for (int i = 0; i < balls.size(); i++)
	118.	   {
	119.	     Ball b = (Ball)balls.get(i);
	120.	     b.draw(g2);
	121.	   }   
	122.	  }
	123.	
	124.	  private ArrayList balls = new ArrayList();
	125.	}
	126.	
	127.	/**
	128.	  A ball that moves and bounces off the edges of a 
	129.	  component
	130.	*/
	131.	class Ball
	132.	{
	133.	  /**
	134.	   Constructs a ball in the upper left corner
	135.	   @c the component in which the ball bounces
	136.	  */
	137.	  public Ball(Component c) { canvas = c; }
	138.	
	139.	  /**
	140.	   Draws the ball at its current position
	141.	   @param g2 the graphics context
	142.	  */
	143.	  public void draw(Graphics2D g2)
	144.	  {
	145.	   g2.fill(new Ellipse2D.Double(x, y, XSIZE, YSIZE));
	146.	  }
	147.	
	148.	  /**
	149.	   Moves the ball to the next position, reversing direction
	150.	   if it hits one of the edges
	151.	  */
	152.	  public void move()
	153.	  {
	154.	   x += dx;
	155.	   y += dy;
	156.	   if (x < 0)
	157.	   { 
	158.	     x = 0;
	159.	     dx = -dx;
	160.	   }
	161.	   if (x + XSIZE >= canvas.getWidth())
	162.	   {
	163.	     x = canvas.getWidth() - XSIZE; 
	164.	     dx = -dx; 
	165.	   }
	166.	   if (y < 0)
	167.	   {
	168.	     y = 0; 
	169.	     dy = -dy;
	170.	   }
	171.	   if (y + YSIZE >= canvas.getHeight())
	172.	   {
	173.	     y = canvas.getHeight() - YSIZE;
	174.	     dy = -dy; 
	175.	   }
	176.	
	177.	   canvas.paint(canvas.getGraphics());
	178.	  }
	179.	
	180.	  private Component canvas;
	181.	  private static final int XSIZE = 15;
	182.	  private static final int YSIZE = 15;
	183.	  private int x = 0;
	184.	  private int y = 0;
	185.	  private int dx = 2;
	186.	  private int dy = 2;
	187.	}

java.lang.Thread

  • static void sleep(long millis)
    sleeps for the given number of millisecond

Parameters:

millis

the number of milliseconds to sleep

In the previous sections, you learned what is required to split a program into multiple concurrent tasks. Each task needs to be placed into a run method of a class that extends Thread. But what if we want to add the run method to a class that already extends another class? This occurs most often when we want to add multithreading to an applet. An applet class already inherits from JApplet, and we cannot inherit from two parent classes, so we need to use an interface. The necessary interface is built into the Java platform. It is called Runnable. We take up this important interface next.

Using Threads to Give Other Tasks a Chance

We will make our bouncing-ball program more responsive by running the code that moves the ball in a separate thread.

NOTE

Since most computers do not have multiple processors, the Java virtual machine (JVM) uses a mechanism in which each thread gets a chance to run for a little while, then activates another thread. The virtual machine generally relies on the host operating system to provide the thread scheduling package.

Our next program uses two threads: one for the bouncing ball and another for the event dispatch thread that takes care of user interface events. Because each thread gets a chance to run, the main thread has the opportunity to notice when you click on the "Close" button while the ball is bouncing. It can then process the "close" action.

There is a simple procedure for running code in a separate thread: place the code into the run method of a class derived from Thread.

To make our bouncing-ball program into a separate thread, we need only derive a class BallThread from Thread and place the code for the animation inside the run method, as in the following code:

class BallThread extends Thread
{
  . . .
  public void run()
  {
   try
   {
     for (int i = 1; i <= 1000; i++)
     {
      b.move();
      sleep(5);
     }
   }
   catch (InterruptedException exception)
   {          
   }
  }
  . . .
}

You may have noticed that we are catching an exception called Interrupted-Exception. Methods such as sleep and wait throw this exception when your thread is interrupted because another thread has called the interrupt method. Interrupting a thread is a very drastic way of getting the thread's attention, even when it is not active. Typically, a thread is interrupted to terminate it. Accordingly, our run method exits when an InterruptedException occurs.

Running and Starting Threads

When you construct an object derived from Thread, the run method is not automatically called.

BallThread thread = new BallThread(. . .); // won't run yet

You must call the start method in your object to actually start a thread.

thread.start();

CAUTION

Do not call the run method directly—start will call it when the thread is set up and ready to go. Calling the run method directly merely executes its contents in the same thread—no new thread is started.

Beginners are sometimes misled into believing that every method of a Thread object automatically runs in a new thread. As you have seen, that is not true. The methods of any object (whether a Thread object or not) run in whatever thread they are called. A new thread is only started by the start method. That new thread then executes the run method.

In the Java programming language, a thread needs to tell the other threads when it is idle, so the other threads can grab the chance to execute the code in their run procedures. (See Figure 1–2.) The usual way to do this is through the static sleep method. The run method of the BallThread class uses the call to sleep(5) to indicate that the thread will be idle for the next five milliseconds. After five milliseconds, it will start up again, but in the meantime, other threads have a chance to get work done.

TIP

There are a number of static methods in the Thread class. They all operate on the current thread, that is, the thread that executes the method. For example, the static sleep method idles the thread that is calling sleep.

Figure 1–2: The Event Dispatch and Ball Threads

The complete code is shown in Example 1–2.

Example 1–2: BounceThread.java

	1.	import java.awt.*;
	2.	import java.awt.event.*;
	3.	import java.awt.geom.*;
	4.	import java.util.*;
	5.	import javax.swing.*;
	6.	
	7.	/**
	8.	  Shows an animated bouncing ball running in a separate thread
	9.	*/
	10.	public class BounceThread
	11.	{
	12.	  public static void main(String[] args)
	13.	  {
	14.	   JFrame frame = new BounceFrame();
	15.	   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	16.	   frame.show();
	17.	  }
	18.	}
	19.	
	20.	/**
	21.	  The frame with canvas and buttons.
	22.	*/
	23.	class BounceFrame extends JFrame
	24.	{
	25.	  /**
	26.	   Constructs the frame with the canvas for showing the
	27.	   bouncing ball and Start and Close buttons
	28.	  */
	29.	  public BounceFrame()
	30.	  {
	31.	   setSize(WIDTH, HEIGHT);
	32.	   setTitle("BounceThread");
	33.	
	34.	   Container contentPane = getContentPane();
	35.	   canvas = new BallCanvas();
	36.	   contentPane.add(canvas, BorderLayout.CENTER);
	37.	   JPanel buttonPanel = new JPanel();
	38.	   addButton(buttonPanel, "Start",
	39.	     new ActionListener()
	40.	      { 
	41.	        public void actionPerformed(ActionEvent evt)
	42.	        {
	43.	         addBall();
	44.	        }
	45.	      });
	46.	
	47.	   addButton(buttonPanel, "Close",
	48.	     new ActionListener()
	49.	      {
	50.	        public void actionPerformed(ActionEvent evt)
	51.	        {
	52.	         System.exit(0);
	53.	        }
	54.	      });
	55.	   contentPane.add(buttonPanel, BorderLayout.SOUTH);
	56.	  }
	57.	
	58.	  /**
	59.	   Adds a button to a container.
	60.	   @param c the container
	61.	   @param title the button title
	62.	   @param listener the action listener for the button
	63.	  */
	64.	  public void addButton(Container c, String title,
	65.	   ActionListener listener)
	66.	  {
	67.	   JButton button = new JButton(title);
	68.	   c.add(button);
	69.	   button.addActionListener(listener);
	70.	  }
	71.	
	72.	  /**
	73.	   Adds a bouncing ball to the canvas and starts a thread
	74.	   to make it bounce
	75.	  */
	76.	  public void addBall()
	77.	  {
	78.	   Ball b = new Ball(canvas);
	79.	   canvas.add(b);
	80.	   BallThread thread = new BallThread(b);
	81.	   thread.start();
	82.	  }
	83.	
	84.	  private BallCanvas canvas;
	85.	  public static final int WIDTH = 450;
	86.	  public static final int HEIGHT = 350; 
	87.	}
	88.	
	89.	/**
	90.	  A thread that animates a bouncing ball.
	91.	*/
	92.	class BallThread extends Thread
	93.	{
	94.	  /**
	95.	   Constructs the thread.
	96.	   @aBall the ball to bounce
	97.	  */
	98.	  public BallThread(Ball aBall) { b = aBall; }
	99.	
	100.	  public void run()
	101.	  {
	102.	   try
	103.	   {
	104.	     for (int i = 1; i <= 1000; i++)
	105.	     {
	106.	      b.move();
	107.	      sleep(5);
	108.	     }
	109.	   }
	110.	   catch (InterruptedException exception)
	111.	   {          
	112.	   }
	113.	  }
	114.	
	115.	  private Ball b;
	116.	}
	117.	
	118.	/**
	119.	  The canvas that draws the balls.
	120.	*/
	121.	class BallCanvas extends JPanel
	122.	{
	123.	  /**
	124.	   Add a ball to the canvas.
	125.	   @param b the ball to add
	126.	  */
	127.	  public void add(Ball b)
	128.	  {
	129.	   balls.add(b);
	130.	  }
	131.	
	132.	  public void paintComponent(Graphics g)
	133.	  {
	134.	   super.paintComponent(g);
	135.	   Graphics2D g2 = (Graphics2D)g;
	136.	   for (int i = 0; i < balls.size(); i++)
	137.	   {
	138.	     Ball b = (Ball)balls.get(i);
	139.	     b.draw(g2);
	140.	   }   
	141.	  }
	142.	
	143.	  private ArrayList balls = new ArrayList();
	144.	}
	145.	
	146.	/**
	147.	  A ball that moves and bounces off the edges of a 
	148.	  component
	149.	*/
	150.	class Ball
	151.	{
	152.	  /**
	153.	   Constructs a ball in the upper left corner
	154.	   @c the component in which the ball bounces
	155.	  */
	156.	  public Ball(Component c) { canvas = c; }
	157.	
	158.	  /**
	159.	   Draws the ball at its current position
	160.	   @param g2 the graphics context
	161.	  */
	162.	  public void draw(Graphics2D g2)
	163.	  {
	164.	   g2.fill(new Ellipse2D.Double(x, y, XSIZE, YSIZE));
	165.	  }
	166.	
	167.	  /**
	168.	   Moves the ball to the next position, reversing direction
	169.	   if it hits one of the edges
	170.	  */
	171.	  public void move()
	172.	  {
	173.	   x += dx;
	174.	   y += dy;
	175.	   if (x < 0)
	176.	   { 
	177.	     x = 0;
	178.	     dx = -dx;
	179.	   }
	180.	   if (x + XSIZE >= canvas.getWidth())
	181.	   {
	182.	     x = canvas.getWidth() - XSIZE; 
	183.	     dx = -dx; 
	184.	   }
	185.	   if (y < 0)
	186.	   {
	187.	     y = 0; 
	188.	     dy = -dy;
	189.	   }
	190.	   if (y + YSIZE >= canvas.getHeight())
	191.	   {
	192.	     y = canvas.getHeight() - YSIZE;
	193.	     dy = -dy; 
	194.	   }
	195.	
	196.	   canvas.repaint();
	197.	  }
	198.	
	199.	  private Component canvas;
	200.	  private static final int XSIZE = 15;
	201.	  private static final int YSIZE = 15;
	202.	  private int x = 0;
	203.	  private int y = 0;
	204.	  private int dx = 2;
	205.	  private int dy = 2;
	206.	}
	207.	

java.lang.Thread

  • Thread()
    constructs a new thread. You must start the thread to activate its run method.

  • void run()
    You must override this function and add the code that you want to have executed in the thread.

  • void start()
    starts this thread, causing the run() method to be called. This method will return immediately. The new thread runs concurrently.

Running Multiple Threads

Run the program in the preceding section. Now, click on the "Start" button again while a ball is running. Click on it a few more times. You will see a whole bunch of balls bouncing away, as captured in Figure 1–3. Each ball will move 1,000 times until it comes to its final resting place.

Figure 1–3: Multiple threads

This example demonstrates a great advantage of the thread architecture in the Java programming language. It is very easy to create any number of autonomous objects that appear to run in parallel.

Occasionally, you may want to enumerate the currently running threads—see the API note in the "Thread Groups" section for details.

The Runnable Interface

We could have saved ourselves a class by having the Ball class extend the Thread class. As an added advantage of that approach, the run method has access to the private fields of the Ball class:

class Ball extends Thread
{
  public void run()
  {
   try
   {
     for (int i = 1; i <= 1000; i++)
     {
      x += dx;
      y += dy;
      . . .
      canvas.repaint();
      sleep(5);
     }
   }
   catch (InterruptedException exception)
   {
   }
  }
  . . .
  private Component canvas;
  private int x = 0;
  private int y = 0;
  private int dx = 2;
  private int dy = 2;
}

Conceptually, of course, this is dubious. A ball isn't a thread, so inheritance isn't really appropriate. Nevertheless, programmers sometimes follow this approach when the run method of a thread needs to access private fields of another class. In the preceding section, we've avoided that issue altogether by having the run method call only public methods of the Ball class, but it isn't always so easy to do that.

Suppose the run method needs access to private fields, but the class into which you want to put the run method already has another superclass. Then it can't extend the Thread class, but you can make the class implement the Runnable interface. As though you had derived from Thread, put the code that needs to run in the run method. For example,

class Animation extends JApplet 
  implements Runnable
{ 
  . . .
  public void run()
  { 
   // thread action goes here
  }
}

You still need to make a thread object to launch the thread. Give that thread a reference to the Runnable object in its constructor. The thread then calls the run method of that object.

class Animation extends JApplet 
  implements Runnable
{ 
  . . .
  public void start()
  {
   runner = new Thread(this);
   runner.start();
  }
  . . .
  private Thread runner;
}

In this case, the this argument to the Thread constructor specifies that the object whose run method should be called when the thread executes is an instance of the Animation object.

Some people even claim that you should always follow this approach and never subclass the Thread class. That advice made sense for Java 1.0, before inner classes were invented, but it is now outdated. If the run method of a thread needs private access to another class, you can often use an inner class, like this:

class Animation extends JApplet 
{ 
  . . .
  public void start()
  {
   runner = new Thread()
   {
     public void run()
     { 
      // thread action goes here
     }
   };
   runner.start();
  }
  . . .
  private Thread runner;
}

A plausible use for the Runnable interface would be a thread pool in which pre-spawned threads are kept around for running. Thread pools are sometimes used in environments that execute huge numbers of threads, to reduce the cost of creating and garbage collecting thread objects.

java.lang.Thread

  • Thread(Runnable target)
    constructs a new thread that calls the run() method of the specified target.


java.lang.Thread

  • void run()
    You must override this method and place in the thread the code that you want to have executed.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020