Basic Multithreading in Java

Imagine that you have a sign-in system. However, for each sign-in, it takes half a second to complete. If ten people sign in, it would take five seconds to finish. For a hundred, it would take fifty seconds, and so forth. The run time would increase at a horribly fast rate if the sign-ins were processed one at a time.

But what if we wanted to process all of these sign-ins at the same time? We can solve this problem with multithreading. Multithreading is essentially the use of two or more threads at the same time in order to run a certain process concurrently.

(NOTE : this does not mean that an infinite number of sign-ins will all be processed in 0.5 seconds, as that requires an infinite number of processor cores.)

First, let’s create a dummy sign in class.

public class SignInRequest{
  public static void handleSignInRequest(){
    //insert magical logic here
  }
}

And then make a Request class using the Observer pattern, so that we can create a RequestListener afterwards.

Now, let’s create a new thread that we can run whenever we get a sign-in request.

public class SignInThread extends Thread{

  private SignInRequest request;

  public SignInThread(SignInRequest request){
    this.request = request;
  }
  public void run(){
    request.handleSignIn();
  }
}

At this point, we can use this SignInThread whenever we get a request.

public void onGetRequest(){
  SignInThread thread = new SignInThread();
  thread.start();
}

It is important that you run the start() method and not the run method.

By doing this, we can handle hundreds of sign in request concurrently, making the sign in process much faster.

In particular, threads are powerful when used with a computer with multiple cores.

For example, if you have 100 sign in requests, and multiple processor cores, you can split the sign ins between the cores by creating multiple threads. This means all of your cores can work at full-speed, whereas only one core would be used if it was not multithreaded.

However, you can multithread with a single core as well. However, when you only have one core, multithreading will not give any speed boosts, and it would be practically the same as if your code was single-threaded.

The most well-known use for multithreading is when you have a GUI. Consider a GUI program that calculates giant numbers. What happens if the calculation takes 30 seconds, and you decide to cancel the calculation? If the program only had a single-thread, this task would be impossible. The user cannot click the cancel button until the calculations are done. However, if it is multithreaded, then the calculations are completely separate from everything else. As a result, the user would be able to click the cancel button, since the calculations are done on a separate thread.

Multiple threads, with multiple cores, will cause your code to run much faster. Faster code, higher efficiency, and the ability to multitask. What’s not to like?

Advertisements

Sorting Lists with a Comparator

You receive a list of names, and you’re told to sort them alphabetically.

“Well, that should be easy!” you think. You can just iterate through the list and sort it with merge sort or quick sort.

But why go through all that effort, when you can just use a Comparator?

public void sortListAlphabetically(List list){
  Collections.sort(list, new Comparator(){
    @Override
    public int compare(String a, String b){
      return a.compareTo(b);
    }
  }
}

Collections.sort takes in two parameters : a List and a Comparator.

You can override Comparator‘s compare method and specify how the sorting will work. In this case, the compareTo method compares the first string with the second, alphabetically. It does this over and over again, comparing each String to the next (using merge sort) until the whole list becomes sorted alphabetically.

Of course, since a Comparator is a functional interface, meaning it only has one method, you can call it in a more elegant way via a lambda statement.

public void sortListAlphabetically(List<String> list){
  Collections.sort(list, (a, b) -> a.compareTo(b);
}

No @Override tags. No method names. No bloated code.
Just elegance and simplicity.

Nulls and Nulls and Nulls, Oh My!

As you’re typing away at your keyboard, creating new objects and methods, you realize something.

“Hey, what if this object is actually null?”

And so, you decide to cleverly check if the object is null, like so :


public void doStuff(Object object){
  if(object != null){
    //Work your magic on this object
  }
}

However, there are several problems with this approach. For instance, most programmers who use this technique do nothing if the object is null. This causes huge amounts of bugs and headaches for everyone.

In addition, null checking an object everywhere causes excessive bloating. In fact, most of these checks are unnecessary. You should not be checking if an object is null inside the main parts of your code. It is best to only check when data is first passed in.

An analogy for this is as follows :

A city, known for its wealth and prosperity, lies in the middle of a desert. Every one in the city is confirmed to be a good citizen, and crime rates are at an all-time low 0%. However, one day, a group of vandals approach the city. As they reach the outskirts, they are caught and kicked out. No criminals allowed!

The city continues to prosper for the rest of eternity.

However, a few dozen miles away, another city named Nullville exists. Unlike the other city, Nullville has no guards around the city. As a result, the city is flooded with nasty and evil people. To combat these evil-doers, Nullville decides to enforce a strict system of identification, with all good people getting an ID.

If you want to go outside, you need to show your ID. If you want to buy meat, you need to show your ID. If you want to go home, you need to show your ID. If you want to sleep, you need to show your ID. If you are caught without an ID, you are booted from Nullville, as you’re proven to be evil.

Clearly, Nullville is in a terrible situation. In order to do anything in Nullville, you first have to actually prove that you have an ID (proving that you’re != null). Even if you aren’t serial killer or a thief, you still have to prove that you have an ID.

As a result, like Nullville, programmers end up excessively checking their data for nulls, when it simply isn’t necessary. As in the first city, data should be checked on the outskirts of your code, not inside the main parts of it.

If you force functions on the “outskirts” of your code base to check for nulls, then you do not have to check for nulls in the core sections. The output is already guaranteed to not be null, so there is no reason, in the input of another function, to check for null.

In a nutshell, a contract needs to be made. Function A promises to return an object, but it isn’t null. Function B accepts an object, but trusts function A that the object will not be null. As a result, there is no reason for function B to check its input for null.

So don’t bloat your code. Check for nulls at the gates of your code, so that you don’t have to do it inside the code.

Exception Swallowing

Exceptions are a fundamental part of a program. For example, if you creating, editing, and closing a database, an exception is needed in case anything goes wrong. However, exception handling can go awry when the exception is swallowed.

Consider the following snippet :

try{
    db.open()
    db.modifySomething();
    db.close();
}
catch(Exception ex) {
   //exception is swallowed
}

If the database throws an exception anytime between opening the database, and closing the database, then the database will simply not close. This can cause huge problems over time, as dozens of unclosed databases would exist at the same time.

The goal of exceptions isn’t to make your life more difficult. The goal is to help you, the programmer, catch errors in your code, and to give you a stack trace so that you know where your code has a problem.

Consider this scenario :

A car drives down a road, but the engine catches on fire. The man inside the car, instead of getting out, opts to continue driving and dies after the car explodes.

Or, the more logical scenario :

A car drives down a road, but the engine catches on fire. The man realizes this, so he gets out of the car immediately. He sees there is a gas leak. The car explodes, but the man survives.

The first scenario is a prime example of what would happen if the exception was swallowed. Not only does the man not know why the engine caught on fire, but he also died.

However, the second scenario shows what would happen if the exception was handled. First, the man escaped safely from the car. In addition he also knows why the engine caught on fire. Similarly, a programmer who properly handles exceptions can find out where the program went wrong, as well as why it went wrong.

Here’s a general rule of thumb :
Fail fast, fix it fast.

Terrible Variable Names

Every time I see an arbitrary one letter variable name, or a shortened word that could mean two things, my soul dies a little inside. Although, this problem also applies for classes (though, anyone who makes a one-letter class name is truly evil). Of course, this holds true on the other side of the spectrum as well. (see Spring’s SimpleBeanFactoryAwareAspectInstanceFactory).

But nonetheless, the focus of this post will revolve around programmers who use vague and terrible variable names.

Consider this following example :

public class dummyClass {

  public void mysteryMethod(Riders[] r){
    Plane p = new Plane();
    List<Riders> ratp = new ArrayList<Riders>();
    FlightAttendant afc = new FlightAttendant(plane);
    FlightAttendant afp = new FlightAttendant(plane);

    for(Rider a : r){
      p.add(a);
      if(a.isAllergic()){ 
        afc.add(a)
      }else{
        afp.add(a);
      }
    }

    afc.handOutCandy();
    afp.handOutPeanuts();

    p.takeOff();
  }
}

Although it isn’t clear, here are what each of the variables are :

afc is short for “attendant for candy”
afp is short for “attendant for peanuts”
p is short for “plane”
r is short for “rider”
ratp is short for “riders allergic to peanuts”.

However, the author of this code couldn’t be bothered to write out the full word because “it’s inconvenient”.
Even if you knew what those acronyms stood for, deciphering the code would still be difficult.

Now let’s rewrite that snippet in a more obvious and clean way.

public class dummyClass {

  public void mysteryMethod(Riders[] riders){
    Plane plane = new Plane();
    List<Riders> ridersAllergicToPeanuts = new ArrayList<Riders>();
    FlightAttendant attendanatForCandy = new FlightAttendant(plane);
    FlightAttendant attendantForPeanuts = new FlightAttendant(plane);

    for(Rider rider : riders){
      plane.add(rider);
      if(rider.isAllergic()){
        attendantForCandy.add(rider)
      }else{
        attendantForPeanuts.add(rider);
      }
    }

    attendantForCandy.handOutCandy();
    attendantForPeanuts.handOutPeanuts();

    plane.takeOff();
  }
}

Comprehension in this revised code is much higher, and it requires no outside knowledge. You didn’t need to know any acronyms, and you could have easily figured out the intent of the code in one read-through.

Although longer variable names means more typing, it also means higher readability. It may be annoying to do at first, but in the long run, code with high readability becomes easy to understand and debug.

While it is true that you could write code much faster if you just use single lettered variable names, or obscure variable names, your code becomes unpleasant and painful to read. So please, do your fellow programmers a favor. Stop using terrible variable names.

State-Based Programming

State based programming is the use of “states” to control the flow of your program. For example, in the case of an elevator, it could be moving up, moving down, stopping, closing the doors, and opening the doors. Each of these are considered a state, and what happens next is determined by the elevator’s current state.

For instance, if the elevator has just closed its doors, what are the possibilities that can happen next? It can either move up, or move down. You wouldn’t expect the elevator to stop after closing its doors. Similarly, when an elevator stops, you expect the next action to be the doors opening.

To apply this in programming, you can store its “state” in an enumerator.

public enum ElevatorState {
    OPEN, CLOSED, MOVING_UP, MOVING_DOWN, STOP
}

Now, you can simply check for the current state and dictate what will happen next, based on that state.

public class Elevator
{
    ElevatorState currentState;
    
    public Elevator(){
        currentState = ElevatorState.CLOSED;
    }

    public void changeState(){

        if(currentState == ElevatorState.OPEN){
            currentState = ElevatorState.CLOSED;
            closeDoors();
        }

        if(currentState == ElevatorState.CLOSED 
           && upButtonIsPressed()){
            currentState = ElevatorState.MOVING_UP;
            moveElevatorUp();
        }
 
        if(currentState == ElevatorState.CLOSED 
           && downButtonIsPressed()){
            currentState = ElevatorState.MOVING_DOWN;
            moveElevatorDown();
        }

        if((currentState == ElevatorState.MOVING_UP
           || currentState == ElevatorState.MOVING_DOWN)
           && reachedDestination()){
            currentState = ElevatorState.STOP;
            stopElevator();
        }

        if(currentState == ElevatorState.STOP){
            currentState = ElevatorState.OPEN;
            openDoors();
        }
    }
}

Of course, this is a very simple example. You would need an event handler for when you would call changeState(), or it wouldn’t work properly. But the idea is still there. You start with a state, and continuously change states over and over again. All logic/functionality depends on what your system’s current state is in.
 

The Importance of Unit Testing

Click click click. Tap tap tap. John sat at his desk, frantically searching for the elusive bug that plagued his code. No matter what he did, the software always returned the wrong result.

Kevin, a friend, took a look over at the code and found this snippet inside a method:

    int x = inputBox.getNumber;
    boolean z = (x%2==0) ? true : false;

    if(z = true){
        return 0;
    }else{
        return 1;
    }

John had made a simple typo on line 4. Instead of checking for equality, he had set z to true, meaning the program always returned 0.

Of course, John had used this method dozens of times in other methods, which then were used in even more methods. With the bug nested several functions deep, John lost several nights of sleep until he discovered the mistake.

Scenarios like these are common, and could have been avoided by unit testing.


What is unit testing?

Unit testing is essentially breaking your application into tiny tiny parts, and testing each of those parts to make sure they work properly. All of these tests are separate, and ensure that your code functions as it should.

Higher-level functions depend on lower-level functions, so by testing those lower-level functions, you can ensure that any function x that depends on a function y will run smoothly. Unit testing will allow you to be confident that your function y works correctly, and that any method that depends on function y will also work correctly, as long as the logic is correct. In addition, if function x is tested, and function y is changed, you can be sure that your change doesn’t break function x as long as all the tests pass. Having key functions tested will allow you to confidently and safely revise code without fear of causing random bugs in other parts of the software.

But Henry! I don’t have time to do unit testing. It takes up too much time!”

While this is a common argument against unit testing, and may hold true for tiny projects, unit tests pay off in the long run by several magnitudes. Although you might initially make much faster progress by neglecting unit tests, your code will ultimately be buggier and less stable, which in turn, will drain huge chunks of your time and ruin your productivity. By doing unit tests, your progress will be almost linear throughout the project because you will spot bugs before they become dozens of layers deep in your code. In addition, you can safely refactor without breaking any functionality, which reduces code rot, increases productivity, and improves the quality of your code base.

Unit tests are an efficient and easy way to decrease the number of bugs in your code, which would otherwise cause long nights with caffeine. Writing unit tests can boost your confidence in your code, and if you can’t trust that your code works, then what can you trust?