Middle School

Overview: 
Explore the concepts and details of using more than one Thread of execution in a program.
Objectives: 

Understand what Processes and Threads are and what it means to have multiple Threads active in Java program. Gain a basic understanding of how to use Threads.

 

Content: 

An executing Java program is called a Process. That process executes your instructions (program) sequentially following the path you created when you wrote your program. This single path is called a thread. As such, your program is only doing one activity (Java statement) at a time and working on one task (your programs list of statements) at a time. For most situations, this works fine. But there are times when you would like to have your program doing more than one thing at time. Using Java Threads it is possible to create additional threads or paths of execution that run in parallel with the main (or first) thread. The effect is that your program can be doing more than one thing (task) at a time. Doing robotics on our platforms you will not need additional threads (multi-threading) most of the time but there are some cases where multi-threading can be useful. Threads can be used to simplify the main path in your program or to perform repetitive tasks while the main thread is busy with something else, sleeping or waiting for some user action.

Like many aspects of programming in Java (and other languages), threads are simple in concept but potentially complex in implementation. There are several ways to do threading and multi-threading can create very interesting and hard to find bugs in your program. But it is possible to keep it simple and get benefit from multi-threading without getting into too much of the possible complexity. We are going to explore basic threading here and there will be example programs in each of the platform sections. It is probably best for you to go now to the section for your hardware platform and work through the examples until you come to the one on using Threads. Then return here to finish this lesson.

When creating a new thread of execution in a Java program, there are two ways to do it. You can use the runnable interface or you can extend the Thread class. We are only going to look at extending the Thread class.

When creating a new thread, the main thing we need to define is the code you want executed in that thread. When you create a new thread, you are telling the JVM here is a bit of code, start running it separately from the main thread and run it until the code path comes to an end. The thread code can have it's own private variables that exist only while the thread is running and the thread shares the class level variables of the class that creates the thread, assuming the thread class is an inner class. An inner class is a class within a class and doing threading with inner classes greatly simplifies things.

Lets look at a simple example:

Here the main thread prints the value of i every half second and the thread increments the value every second. You can see by the results of this code that the two threads run independently of each other.

The code we want to run in the thread is put in the run() method of the thread class. Threads are started with the start() method and stopped with the interrupt() method. When thread.interrupt() is called, the Thread class isInterrupted() method returns false. You should look for this to exit your thread code. If you happen to be in a blocking method when interrupted, sleep() in this case, the InterruptedException will be thrown. You normally just ignore that exception as it is just another signal to stop your thread code. The second catch statement catches and reports any errors that might occur in your code.

Here is this example in CodingPoint. Threads can be used in many ways and there are many methods on the Thread class for managing and coordinating threads. More complex threading is beyond the scope of this lesson and if you use threads it is best to keep it simple as shown here.

When doing multiple threads, you frequently need to share data between threads. Coordinating access to shared variables is called concurrency and is a complex and multi-faceted subject. Java contains many features to allow threads to coordinate write access to shared variables and objects by multiple thread. Again these features are beyond the scope of this lesson. To keep it simple and avoid concurrency issues, follow this rule: variables should only be updated by one thread. They can be read by several threads but only changed by one. In the above example, only the MyThread class changes the value of variable i.

Here is a simple tutorial and a video on multi-threading. Here is a more detailed tutorial including concurrency and here is the official Java documentation on threading.

 

 

Navigation:

Overview: 
Explore how the Singleton Design Pattern is used to simulate a static class.
Objectives: 

Understand the Singleton Design Pattern and how it is used.

Content: 

In a previous lesson, we discussed static variables and methods. Static variables and methods are available without an instance of their containing object and are shared with all other object instances that exist in your program. This is used for global variables and utility methods that don't really have the aspect of multiple instances that many objects do. We also said that Java does not support static classes. Lets explore the idea of static classes in more detail.

A static class would be useful when you will have only one instance of a class in existence at any time in your program. A robotics example might be a class that handles the teleop phase of the robot game. You really would not want to have more than one instance of your teleop class existing at the same time since the hardware interface can't be shared. So it would be nice to be able to define your teleop class as static.

Since you can't, you could define all variables and methods in your teleop class to be static and that would technically achieve the result you are looking for. However, it would still be possible to use the new keyword and create multiple instances of your teleop class. This would not make much sense as the fields and methods are static. However, you can disable the new keyword for a class by marking the class constructor private. Now you can't create instances of the teleop class with new and you have to access the class variables and methods using the class name. This will work but at the end of the day it is kind of messy and different than most classes you would write in Java.

A better alternative might be a regular class that is limited to a single instance and that single instance is shared when you ask for a new instance of that class. This can be done using the Singleton Design Pattern.

A quick note about design patterns. Design Patterns are coding techniques or design ideas shared by programmers across the world. Like code libraries, design patterns are idea or concept libraries. Singleton is a design pattern that describes a way to have a single instance object. This is how it works:

To create a Singleton class, you add a private class level static variable with the data type of the class itself. Next you mark the class constructor as private to disable the Java new keyword. Finally you add a method called (by convention) getInstance(). The getInstance() method checks to see if the static class variable is null, and if it is null, creates an instance of the class and stores the reference in the class variable and returns the reference to the caller. If the static class variable is not null, getInstance() returns the existing reference to the single existing instance of the class to the caller. In this way all callers to getInstance() get the same reference to the single instance of the class. The rest of the class can be written just like a normal class and the variables and methods are accessed via the instance reference in the calling class.

Here is an example of a singleton class:

Here is how this might be used:

Here we have 3 references to the singleton class but only one actual object instance has been created. Note that the variable instanceCount and method getInstanceCount() are coded and accessed just they would be in a normal class. This code would print out:

inst=1;req=3
inst=1;req=3
inst=1;req=3

Here is the example code in CodingPoint. Here is a video dicussing the Singleton pattern.

Singleton classes can be difficult to understand at first, but are very useful in Java programming and in robotics in particular.

 

Navigation:

Overview: 
Explore the concept of static fields and methods.
Objectives: 

Understand what static fields and methods are and how and when to use them.

Content: 

Normally, class members (variables and methods) are accessed via an instance reference. Leaving methods aside for the moment, this is because class variables exist separately for each instance of a class (created with the new keyword). If you have a variable x in a class and create two instances of the class, each instance will have its own x variable, access to which is by the instance reference. You also access methods via the instance reference. Here is an example:

The result:

theVar=3   theVar=7

Instance1 and instance2 refer to separate object instances of the class and as such each has its own theVar variable which has its own value. The variable is said to be an instance variable.

What if we would like to have a class level or global variable? One that is not specific to any instance of the class but exists as a single copy in memory at  the class level? We can do that with the static modifier. Marking a variable as static means there is only one copy of the variable for all class instances. The static variable is created when first accessed and persists as long as the program runs. Any instance of the class can access the static variable as it is shared among all instances of the class.

Since static variables are not accessed via an instance reference, you use the class name with a dot to access the variable.

You can also mark methods as static. This means the method does not need an instance reference to be called. The method is class level or global. Note that static methods can only access the static variables in the same class. Non-static or instance methods can access static and instance variables. Here is an example:

This example would print out:

instance count=0
instance count=3

The example uses a static variable to count how many instances of MyClass are created. We increment globalCount in the class constructor. This would make globalCount = 2 but to demonstrate static variable access, we directly increment globalCount to 3. We can do this since globalCount has public access. Note that the first output is zero because we called the static method which caused the static globalCount varible to be created and initialized, but we have not yet created any instances of the class. Note that the last statement would generate a compile error since we are accessing a non-static variable through a static (class name) reference.

Here is the example above on CodingGround. Fix the error and demonstrate the program.

Here are two videos (video1, video2) about static members. Here is a detailed discussion of static members.

Note: While classes can't normally be labelled static, an inner class, that is a class within a class, can be. We won't dicuss this as it is beyond the scope of this curriculum, but the use of the static keyword on the inner classes in our CodingGround examples is required when inner classes are defined in the same class as the main() method.

 

Navigation:

Overview: 
Explore logging or tracing of data by a Java program on a robot for later examination. This is a common technique to debug programs.
Objectives: 

Understand logging basic concepts.

 

Content: 

Logging, also called tracing, is the practice of recording debugging information from your program in a disk file for later examination. When logging, you place method calls in your program to call either the Java Logging system or helper methods in code provided by this course. As said in the last lesson, file output is a topic beyond the scope of this curriculum and the details of using the Java Logging system directly are as well. But, due the usefulness of logging in debugging robot programs, we are providing you with code to do logging for you. In each of the three sections on the FIRST robotic platforms, there will be a lesson on how to implement logging in your programs.

It is really pretty simple. You add a .java file containing the logging code to your project and then in your own code, you can call one of the logging methods provided by the logging code to record whatever information you think is useful to a file on the robot controller. You then use the appropriate utility program to pull that file back to your development PC where you can examine it. Each record in the log file contains the time of day, the class in your code where you called the log method and the source file and line number where that call is located. This makes it easy to go from the log file back to your code.

 

Navigation:

Overview: 
Short discussion of using data files and doing input/output in Java. As file I/O is rarely used in the robotics we are targeting, this is a minimal discussion.
Objectives: 

Understand how input/output with disk files fits into robotics programming and where to go for more information.

 

Content: 

Writing data to and reading data from disk files is a common activity for Java programs in many situations. However, file input/output (I/O) is rarely used in the programs created for robots on the platforms we are working with. As such, and given that file I/O is a large and complex topic, it is not going to be covered here. For those who are interested, here are some resources where you can learn more:

File I/O in Java is done with classes available in the java.io package. You can read about it here and many other places on the web. A newer package of I/O classes was released with Java 7 called java.nio.file and you can read the official documentation here.

 

Navigation:

Overview: 
Explore the concept of exceptions in Java.
Objectives: 

Understand what exceptions are and how to use them to handle errors in Java programs.

Content: 

When running a Java program, if the JVM detects an error it will generate an error condition called an Exception. An Exception is actually an object that contains information about the error and is available for your code to capture and handle as needed. Generating an exception is called throwing, since all Exception objects are subclasses of the Java Throwable object. when an exception occurs, execution of your program stops at that point and the JVM will look for special code that handles exceptions. If an exception is not explicity handled by your code, the JVM will abort your program and report the exception details to the console.

An Exception object identifies the type of exception, indicated by the specific Exception object thrown. There are many pre-defined Exception objects descended from Exception such as IOException or ArithmeticException. An Exception object will contain the location in your program where the exception occurred (stack trace) and may include a description (message).

The most common exception you will encounter is the NullPointerException. This occurs when you attempt to use an object reference variable that has not been set to a valid object reference. Here is an example of this exception in CodingPoint. Compile and run the program to see the exception abort the program and report its information to the console. You can then comment out line 7, compile and run again. This will demonstrate how the stack trace information shows the where in a hierarchy of method calls the exception occurred.

What if you would like to catch exceptions and handle them in some other manner than aborting your program? Java provides a way to do that with try/catch/finally blocks. The general form of a try/catch/finally block is:

This says try executing the code in the try block and if an exception occurs, pass the exception to the catch block, which executes the statements in the catch block (your error handling code). If there is no exception, execution passes to the next statement after the catch block. The code in the optional finally block is always executed exception or not, and execution proceeds to the next statement after the finally block.

Here is an example in CodingPoint of catching an exception. You can compile and run the example and then uncomment the finally block and compile and run again to see how the finally block works. You can also comment out the call to myMethod to see how finally works when there is no exception.

Note that the exception occurred in myMethod but the try/catch block in the main method handled the exception. This is because Java will work its way back through a method call hierarchy until it finds a try/catch block that can handle the exception. Notice we said "finds" a try/catch block that can "handle" the exception. This is because a catch can specify a specific Exception it will handle. If the exception being caught matches an Exception class specified on a catch statement, that catch will process the exception. This is coupled with the fact that you can have multiple catch statements and so tune your exception processing by Exception type.

Here is an example in CodingPoint showing multiple catch statements handling the NullPointerException differently than all other exceptions.

When designing your programs you can use Exceptions for your own error handling. You can trigger exception handling just like Java with the throw statement. You simply throw the exception you want handled:

This will throw the standard Java Exception with your text as it's message.

You can also extend the Exception class to create your own Exceptions. Here is an example in CodingPoint showing how to use exceptions to handle your own error processing. Compile and run to see the generic Java exception used. Then comment the first throw out and uncomment the second. This will show the use of a custom Exception. Finally you can uncomment the catch for the MyException class and see how you can trap custom exceptions.

Note that if you throw exceptions in a method, the throws Exception specifier must be added to the method definition.

Here is a series of videos (video1, video2, video3, video4) about Exceptions and here is a detailed discussion of Exceptions.

 

Navigation:

Overview: 
Explore some of the advanced data types available with Java.
Overview: 
Explore how Java converts between different data types.
Objectives: 

Understand Java's data conversion features which are called Casting.

Content: 

Java provides the ability to convert from one data type to another within a set of rules. Some conversions are made automatically and some you have to explicitly request.

Here is a discussion of converting between primitive data types.

Here is a discussion of converting between reference (object) data types.

Here is a video about casting.

 

Navigation:

Overview: 
Explore basic variable collections in Java.
Objectives: 

Understand basic collections, what they are, how they work and how to use them.

Content: 

A Collection is an object that stores lists of other objects allowing the group of stored objects to be manipulated in many powerful ways. A Collection may sound like an array or ArrayList and while a Collection is quite different than an array, ArrayList is in fact one implementation of the Collection concept. Java has a large number of specific implementations of the Collection concept you can use. Here are the most commonly used types of Collection:

  • set - A list of objects with no duplicates.
  • list - A list of objects duplicates allowed. (ArrayList is an implementation of the list general type)
  • map - A list of objects with key values (no duplicates).
  • queue - A list of objects with features that support sequential processing of the elements.

Within each type, there are a number of actual implementations you can use. Each implementation has specific features or performance aspects that you consider when choosing an implementation to use for your programs. Here is an example:

This prints out:
second string
third string
first string
The example creates a Set of String objects stored in a HashSet implementation. A HashSet is a high performance Set but does not guarantee any particular order when retrieving elements from the Set. Note that since this is a Set, the second attempt to add "first string" to the collection is ignored since there is already a duplicate element in the Set.
 
Collections have methods for adding, deleting and retrieving elements and much more. One useful feature of Collections is the Iterator. An Iterator is an object you can retrieve from the Collection that provides methods for navigating and modifying the list. Using an Iterator you can move forward and backward on a Collection using next and previous. Note the for keyword in the example. The Java for keyword understands Iterators and supports using them to access Collection elements.  Here we we are saying do a for loop for all of the elements in mySet, type the elements as String and give me access to each element through the variable s.
 
Here is an example of a List type Collection:

This prints out:
new first string                                                                                                                                       
first string                                                                                                                                           
second string                                                                                                                                          
third string
second string
--------------------
second string
third string
second string
first string
new first string

Here we create a List type Collection using the ArrayList implementation and add some elements. Note we added an element using an index (position) and it inserted the element at that location, moving all subsequent elements up. The ArrayList allows us to add a duplicate element. Finally we use the Iterator type ListIterator (a specialized Iterator for List collections) to manually list the elements in forward order and then reverse order. Note that the ListIterator to go in reverse order is created with it's starting position set to the last element in the list by using the list length field to identify the last element's position.

Due to the many types of Collections and the many implementations of the types of Collections, Collections can seem daunting and overly complex. Collections are very powerful tools for manipulating data sets but most cases can be handled by the ArrayList Collection type.

Here is a video on the ArrayList Collection type. Here is a detailed discussion of Collections starting with an introduction and moving through the specific implementations of the various Collection types.

Here is the example code in CodingGround. Add code to the example to use the iterator for myList to locate the element containing "third string" and remove it from the list. Print out the modified myList to confirm the removal.

 

Navigation:

Overview: 
Explore variable arrays in Java.
Objectives: 

Understand what arrays are and how to use them.

Content: 

An array is a special object used to store a list of variables of the same data type. An array is defined like this:

This statement defines and then creates an array of 3 integer variables (or elements) which will be addressed as a list. The new keyword defines the size of the array. We can then put values in the array and access them with an index value (position) in the array. Arrays are indexed starting at zero:

Note that we can initialize array values with the new keyword:

Arrays may have more than one dimension:

For loops are especially useful in processing arrays:

This will print out:

row 0 col 0 = 5
row 0 col 1 = 10
row 1 col 0 = 15
row 1 col 1 = 20

Notice the array has a built-in field called length that tells the size of the array.

Arrays are fixed in their dimensions once created so the array size can't be changed. If you need dynamic array sizing, that is, you want to change the size of the array as your program proceeds, you can use a class called an ArrayList. The ArrayList is defined in the java.util package. An ArrayList has methods that allow you to add and remove elements on the fly:

String s will contain "A different String object". Why? Because when we removed element zero, the rest of the elements shifted down.

ArrayLists have a number of methods you can use to manipulate the array. Note that the ArrayList can only contain object instance references (no primitives). Also note that when we created the ArrayList, we specified the type of object that would be contained in the ArrayList.

The for statement has a special case called for-each that applies to arrays and collections (next lesson). This special for statement will automatically provide each element in an array to your code in the for statement or block:

ArrayList is just one of many types of Lists (called Collections) available in the Java API.

Here is a video about single dimension Arrays. Here is a video about multi-dimension Arrays. Here is a detailed discussion of Arrays.

Here is the example code on CodingGround. Add code to the example to add up all the elements in array x1 using a for loop and print the result. Add another for loop to print the strings in ArrayList a1.

 

Navigation:

Pages