Agenda
- Java Basics
- Strings and Scanners
- File I/O
- Threads
IDE
Eclipse IDE for Java Developers:
- http://www.eclipse.org/downloads/packages/eclipse-ide-java-developers/heliossr1
To run a file from the command line:
- > javac Project1.java && java Project1
Classes and Methods
- Classes are containers for related fields and methods
- Methods can access/mutate fields, and also have side effects
(e.g., printing to the screen)
- In Java, we always put our code in a class with the same name
as the file
- The main method (run from command line) must also be in a
class.
Interfaces and Generics
Interfaces
- Classes can implement interfaces
- Implementing an interface is promising to provide
implementations of the methods in the interface
- An interface is like a type; methods and classes
can expect parameters and fields to implement a particular
interface
- Interfaces allow methods and classes to require specific
actions from objects they access; they also allow provide a
principled way to change object behavior without altering the way
that object is used
Generics
- Like C++ templates, Java generics
allow metaprogramming by specializing classes at
compile time based on a specified type
- For example:
- public class MyClass<T>
- public <T> MyMethod()
- We see generics as a way to specialize the type of object held
in items of a list (more type safe than abusing the universal base
type Object)
- There's lots more to know about generics, check
out this
tutorial (pdf)
User Input
- At the command line, you can read input from System.in
- It's easiest to wrap System.in with
a Scanner
File Input
- The File
class encapsulates the actions that you can take using files
- Files are opened when you instantiate a new File object
- The constructor can throw FileNotFoundException (must be caught!)
- You will probably want to wrap your File in a Scanner if you
are reading from it; e.g.,
- Scanner input = new Scanner(new File("filename"));
File Output
- FileOutputStream is a convenient class for file output
- Like file input, file output can also be simplified with
wrappers, such as PrintStream
An Exercise
- Use what we've learned so far to fill in Lines.java, a class
which does the following:
- Ask user to give filename and search string
- Read a line from a file
- Search line for search string
- If search string appears, output line to stdout
- Repeat for rest of lines in the file
Threads
- In Java, threads are baked into the runtime
- Synchronization is built into the language, and there are a
lot of high-performance concurrent data structures (in
java.util.concurrent)
- Class Thread
encapsulates thread behaviors
- To use threads, you need a class that implements the Runnable
interface (there's another way, but this is the way we will learn;
the API docs for Thread describe the other way if you are
curious)
Basic Threads Example
- Here is an example of starting and running two threads
- Notice the join() call on each of the threads; this call
blocks until the thread terminates
- What happens if t2 finishes before t1?
- It's okay, because the thread object t2 will
stick around even if the thread dies, and will immediately
return from the join() method call
- Why do you suppose that the numbers print out in sequential
order?
- Will it always happen this way?
- No, not necessarily; try invoking it a few times in a
row
- Exercise: try adding a random sleep to the
print method, then what do you think will print?
ArrayBlockingQueue
- There are lots of library classes provided with the latest
versions of Java to help you coordinate thread
activity
- One of them is
an ArrayBlockingQueue,
which you may want to use in your first project.
- Be aware of all the great classes in java.util.concurrent.*,
and use them wherever appropriate
- Take a look at the API docs for the ArrayBlockingQueue and see
if you can figure out how to use it
Producer/Consumer with ArrayBlockingQueue
- A BlockingQueue (an interface implemented by ArrayBlockingQueue) can serve as the
"mailbox" on which the producer and consumer to coordinate
- Make sure you copy this code to your computer and try running
it yourself.
- try changing the sleep times for the producer or consumer
- try giving the producer and consumer different mailbox
objects (your program will not terminate on its own, can you
think of why? what do you think will be output?)
- See if you can understand the decisions I made in setting up
this simple object hierarchy (including generics); what other
design choices might I have made?
Iterator and Iterable
- Two useful interfaces are Iterator and Iterable
- If you implement them, you can use your object "wherever
iterable things are accepted"
- For example, you could use your object like a collection in a
for-each loop
Using Iterator and Iterable
- Here we create an object that steps over range [start, end) by
step amount
- The main method uses it in a for-each, which is pretty nice!
Mutual Exclusion
- You haven't learned about mutual exclusion
(mutex) in class yet, but you will soon
- A mutex ensures that only one thread at a time is
in a part of the code at once
- a part of the code protected by a mutex is
called a critical section
- There are many ways to protect sections of code, but an easy
way built into the language is to declare a
method synchronized; a synchronized method will only
be run by one thread at a time no matter how many threads are
running your program
Mutex Example
- Think about assembly; i++ can be done in a register in one
instruction (INC Ra), but if I needs to be in shared memory for
multiple threads to access (remember, each thread has its own
private registers), then i++ is more than one instruction
- it requires LOAD, INC, and STORE
- If you don't protect i++ with a mutex (or other more advanced
techniques), then weird things can happen, like one increment
overwriting the other because they happen simultaneously
- Let's look at a long example, it increments a variable over
and over in 4 concurrent threads
- We expect the result to be 4000 (4 threads doing 1000
increments on the same variable)
- The example output is from a run on a dual-core, you can see
that the non-synchronized version can come up with an incorrect
result!
Tips
- Comment all your methods using Java syntax
- Search the Java API docs using google
- Use multiple files to help stay organized
- Write succinct code, try to leverage the nicest syntax you can
(e.g., try to use things like iterators and the for-each loop).
- Learn to use a debugger!