This page contains my notes from the following books:
a) Java: The Complete Reference - Herbert Schildt
b) Beginning Java 8 Language Features - Kishori Sharan
c) Modern Java in Action, 2nd Edition
d) Java Generics and Collection - Maurice Naftalin and Philip Wadler

Index:
Chapter 0: Generics Java TM Tutorials
Chapter 4: Generics (Kishori Sharan)
Chapter 1: Introduction (Naftalin)
Chapter 2: Subtyping and Wildcards (Naftalin)
Chapter 3: Comparison and Bounds (Naftalin)
Chapter 15: Concepts behind CompletableFuture and Reactive Programming
Chapter 11: Multithreaded Programming
Chapter 6: Threads
Chapter 28: The Concurrency Utilities
Chapter ?: Design Patterns

Generics JavaTM Tutorials

Useful Links
- Link to tutorial
- Why does java require a cast for the instantiation of a bounded type parameter to its upper bound class?
- How to reference a generic return type with multiple bounds
-
Generic Types
- Generics enable types (classes and interfaces) to be parameters when defining classes, interfaces, and methods. Much like the more familiar formal parameters used in method declarations, type parameters provide a way for you to re-use the same code with different inputs. The difference is that the inputs to formal parameters are values, while the inputs to type parameters are types.
- A generic type is a generic class or interface that is parameterized over types. A Generic class is defined in the following format: class MyClassName <T1,T2,..,Tn> {/* ... */}. T1 to Tn are called the type parameters or the type variables. The type variable used in defining the class name can be used anywhere within the class. A type variable can be any non-primitive type you specify: any class type, any interface type, any array type(?), or even another type variable(List<List<String>>).
UsingObjectVsGenerics
- Type parameter naming conventions: E - Element, K - Key, N - Number, T - Type, V - Value, S,U,V etc. - 2nd, 3rd, 4th types.

Some commonly used terms

:

Type Parameter and Type Argument

: Many developers use the terms "type parameter" and "type argument" interchangeably, but these terms are not the same. When coding, we provide type arguments in order to create a parameterized type. Therefore, the T in Foo<T> is a type parameter and the String in Foo<String> is a type argument. This lesson observes this definition when using these terms.

Generic Type Invocation

: To reference the generic Box class from within your code, you must perform a generic type invocation, which replaces T with some concrete value, such as Integer. Box<Integer> integerBox is an example of this. Similar to how you would pass an argument to a method invocation, you pass a type argument, Integer in this case, to the Box class itself. An invocation of a generic type is known as a parameterized type.

Raw Types

: Using a generic class or interface without using type arguments is a raw type. For instance, doing Box box = new Box(); is a raw usage of Box<T>. In this case, box would just be a box of Objects.
Generic Methods
- Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter's scope is limited to the method where it is declared. Static and non-static generic methods are allowed, as well as generic class constructors.
- When calling the method in the Test class we have explicitly called the passed the types. This is not necessary and the compiler can mostly determine the types on its own. This is known as type inference.
Expand Gist Expand Code Snippet
Bounded Type Parameters
- There may be times when you want to restrict the types that can be used as type arguments in a parameterized type. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for.
- Question: How is this any different from just using a method with an argument of type Number?
Expand Gist Expand Code Snippet
- The above examples have shown how to use types with a single bound. But you can also combine the bounds to have types with multiple bounds.
- Example: class MyClassName <T extends T1 & T2 & T3>
- A type variable with multiple bounds is a subtype of all the types listed in the bound. If one of the type is a class, it must be specified first. Example:
class A {/* ... */}
interface B {/* ... */}
interface C {/* ... */}
and consider a class that uses all 3 of the bounds as:
class D <T extends A & B & C> {/* ... */};
If bound A is not specified as the first bound then you get a compile error. Remember that you can only extend from one class. Hence there will only be one class present in the type parameter declaration and that class type declaration should be the first one. Read this SO answer for more detail.
Generic Methods and Bounded Type Parameters
- Bounded type parameters are the key to the implementation of generic algorithms. Consider the following two attempts at creating a generic algorithm:
Expand Gist Expand Code Snippet
How do Inheritance and SubTypes work in the case of Generics?
- The primary thing that you have to keep in mind is that although Integer is a subtype of Number, List<Integer> is not a subtype of List<Number>. The below code snippet provides an example of this:
Expand Gist Expand Code Snippet

Chapter 4: Generics

Useful Links
- Angelika Langer FAQs about Generics
- This SO post answers the doubt you had about why we would use public <T extends SomeBaseClass> void myMethod(Class<T> clz) vs public void myMethod(Class<? extends SomeBaseClass> clz)
What is the Problem that we are trying to solve?
- Consider the following:
Expand Gist Expand Code Snippet
- We want to avoid this problem. We want Java to 'know' that we intend to use the instance of ObjectWrapper with String, and want Java to pre-emptively warn us when we try to use it with Integer type.
- Generics lets you specify a type parameter with a type (class or interface). Such a type is called a generic type (more specifically generic class or generic interface). The type parameter value could be specified when you declare a variable of the generic type and create an object of your generic type. If you have difficulty visualizing it, just replace the <T> with String instead.
Expand Gist Expand Code Snippet
- The parameter that is specified in the type declaration is called a formal type parameter; for example, T is a formal type parameter in the Wrapper<T> class declaration. When you replace the formal type parameter with the actual type (e.g. in Wrapper<String> you replace the formal type parameter T with String), it is called a parameterized type. A reference type in Java, which accepts one or more type parameters, is called a generic type.
- A generic type is mostly implemented in the compiler. The JVM has no knowledge of a generic type. All actual type parameters are erased during compile time using a process known as erasure. Compile-time type-safety is the benefit that you get when you use a parameterized generic type in your code without the need to use casts.
Supertype-Subtype Relationship
- Note that Wrapper<String> is not assignment compatible to Wrapper<Object>.
- In the below example, if you were able to assign as reference of strWrapper to objWrapper, the compiler would not be able to make sure that the strWrapper will store only a reference of a String type.
- Remember that a String is an Object because String is a subclass of Object. However, Wrapper<String> is not a Wrapper<Object>. The normal supertype/subtype rules do not apply with parameterized types.
Expand Gist Expand Code Snippet
How to create a Generic Array
- // TODO
- Go through this SO Link.
Raw Type
- The code may use (though it is not recommended) a non-generic version of a generic class by just omitting references to the generic type parameters. The non-generic version of a generic type is called a raw type. Using raw types is discouraged. If you use raw types in your code, the compiler will generate unchecked warnings.
Expand Gist Expand Code Snippet
Unbounded Wildcards
- Suppose we want to print the details of the Wrapper class for which we create a method. What should be the args that should be input into the method. This is the first version of the solution. Since the printDetails() method is supposed to print details about a Wrapper of any type, Object as parameter type seemed to be more suitable. (Not using T as a parameter type right now. Probably come back to that later.)
Expand Gist Expand Code Snippet
- As you can see the above code generates a compile-time error. We already looked at why this error is generated, it's because Wrapper<String> and Wrapper<Object> are not assignment compatible.
- This is the problem that wildcards allows us to solve.
- A wildcard type is denoted by a question mark, as in <?> . Think about how you can assign a reference of any type to a reference of an Object type. In the same way, you can assign generic of any type to a generic of a wildcard type.
- The question mark in a wildcard generic type (e.g., <?>) denotes an unknown type. When you declare a parameterized type using a wildcard (means unknown) as a parameter type, it means that it does not know about its type.
Expand Gist Expand Code Snippet
- There is a complicated list of rules as to what a wildcard generic type reference can do with the object. However, there is a simple rule of thumb to remember. The purpose of using generics is to have compile-time type-safety in Java programs. As long as the compiler is satisfied that the operation will not produce any surprising results at runtime, it will allow the operation on the wildcard generic type reference.
- I think what you basically have to wrap your head around is this: The class Wrapper is defined as Wrapper<T>. Whenever you will instantiate the Wrapper class, you will do it like this for example: Wrapper<String>. So the compiler will know that you intend to use this class with a String type. The getRef and the setRef methods in the class make use of the T parameter either as argument to a function, or as a return type. Once you have made it clear that T is in fact String (by instantiating the Wrapper class with Wrapper<String>, you are essentially telling the compiler that you intend to use the Wrapper<T> class as a Wrapper<String> class. Hence the compiler can go ahead and replace all occurrences of T with String) the compiler can then kick-in and perform all the necessary checks it needs to do to make sure that there are no surprises during run-time.
- But then, you can also instantiate the class as Wrapper<?>. Now you are telling the compiler that you don't know what the type of argument or the return type of the methods in this class are going to be. So if you use something like String str = unknownWrapper.getRef();, the compiler is going to complain and say:
- Hey you never said that the getRef method is supposed to return just String. What if you created a wrapper class with something like this: Wrapper unknownWrapper = new Wrapper<>(1234);. Then what am I supposed to do at this line of code: String str = unknownWrapper.getRef(); I am going to show you a compile error so that you know that is not right. If you do this String str = (String) unknownWrapper.getRef();, I will no longer show you the compile error, but you are still going to get a ClassCastException at runtime. All I know is that the getRef is going to return an unknown type, and that unknown type is going to be atleast an Object. So the best you can do is write Object obj = unknownWrapper.getRef();.
- Now why do I show compile errors when you are trying to use setRef?
- Why does the setRef(new Object()) method generate a compile-error as well? Field<?> means Field<? extends Object> and when you have ? extends Something you can only get values out of it, you can't set values in it except null (Source on DZone).
- Can't add value to the Java collection with wildcard generic type
- Java Generics Wildcard confusion [duplicate]
- Java Generics Tutorial
Upper-Bounded Wildcards
- The upper bound of a wildcard is expressed as <? extends T>. Here T is a type. <? extends T> means anything that is of type T or its subclass is acceptable. For example Number is a type, and Integer, Double are its subclasses. Hence if we want the args to be only of type Number or one of its subclasses, we write Wrapper<? extends Number>
- Suppose the problem was to add two numbers. The first solution that you could come up with could look like this:
Expand Gist Expand Code Snippet
- Finding the sum of an Integer and a String obviously does not make any sense. But the code still compiles, and will generate errors only during runtime. Hence we want to restrict both of the args to be a Number or a subclass of a Number. Hence we know the upper-bound of the type of the actual parameter that the Wrapper object should have. (It's upper-bound because recall that in the inheritance tree, the super class is higher and the subclass is lower in the tree with the subclass having a directed arrow to the superclass. Hence Number is an upper bound).
- Hence we rewrite the code as:
Expand Gist Expand Code Snippet
- Note the following code snippet:
Expand Gist Expand Code Snippet
Lower-Bounded Wildcards
- The lower bound of a wildcard is expressed as <? super T>. This means "anything that is of type T or is a supertype of T is acceptable".
- Let us first take a look at the wrong way of doing it. The below code will generate a compile-time error because the copy() method requires the source and the dest arguments be of the same type. See how one version of the copy_v1() method compiles properly while the other one doesn't? Asked a question about it here on SO..
Expand Gist Expand Code Snippet
- So what does the right way look like? For all practical purposes a String is always an Object. Here, you need to use a lower-bounded wildcard.
Expand Gist Expand Code Snippet
Generic Methods and Constructors
- You can define type parameters in a method declaration. They are specified in angle brackets before the return type of the method. The type that contains the generic method declaration does not have to be a generic type.
Expand Gist Expand Code Snippet
- You can use the type parameter specified for the generic type inside the non-static method declaration. The new type parameter V forces the first and the second arguments of method m1() to be of the same type. The third argument must be of the same type T, which is the type of the class instantiation.
Expand Gist Expand Code Snippet
What is recursive type parameter in Generics? And why is it used?
- Excellent answer here on SO.
- Assume that we have to sort the fruits by their sizes. And we are told that we can only compare fruits of the same types. For example, we can't compare apples with oranges.
Expand Gist Expand Code Snippet
- So what is the problem with the above solution? The problem here is that the code for implementing the compareTo() method is duplicated for Apple and Orange class. And will be duplicated more in all the classes that we extend from the Fruit, for creating new fruits in the future. The amount of repeated code in our example is less but in real world the repeated code can be of hundreds of lines in each class.
- So we come up with the following solution. In this step, we get rid of the repeated code of compareTo() method by moving it to a superclass. Our extended classes Apple and Orange are no longer polluted with common code. But now the problem is that we are now able to compare different types, comparing apples to oranges no longer gives us an error.
Expand Gist Expand Code Snippet
- So we try a different approach where we try to introduce a type parameter. To restrict comparison of different types, we introduce a type parameter T. So that the comparable Fruit<Apple> cannot be compared to comparable Fruit<Orange>. Note our Apple and Orange classes; they now inherit from the types Fruit<Apple> and Fruit<Orange> respectively. Now if we try to compare different types, the IDE shows an error, which is our desired behaviour. But in this step, our Fruit class doesn't compile. The getSize() method of T is unknown to the compiler. This is because the type parameter T of our Fruit class doesn't have any bound. So, the T could be any class, it is not possible that every class would have a getSize() method. So the compiler is right in not recognizing the getSize() method of T.
Expand Gist Expand Code Snippet
- So to solve this problem, we finally introduce the Recursive Type Parameter. So, we tell the compiler that our T is a subtype of Fruit. In other words, we specify the upper bound T extends Fruit<T>. This makes sure that only subtypes of Fruit are allowed as type arguments. Now the compiler knows that the getSize() method can be found in the subtype of Fruit class (Apple, Orange etc.) because the Comparable<T> also receives our type (Fruit<T>) that contains the getSize() method. This allows us to get rid of the repeated code of compareTo() method and also allows us to compare the fruits of the same types, apples with apples and oranges with oranges.
Expand Gist Expand Code Snippet
Sample Question and Code
- Implement class that will merge two inputs, remove duplicates and return values one by one. It should have a method to return values one by one and has next() method.
Expand Gist Expand Code Snippet

Chapter 1: Introduction

"New" features introduced in Java
- These are some of the features we will be looking at in this chapter:
a) Generics
b) Boxing and Unboxing
c) For-Each
d) Generic methods and variables
Generics
- An interface or a class can be declared to take one or more type parameters. These are written in angle brackets. These parameters need to be supplied when you declare a variable belonging to the class, or when you create a new instance of the class.
- Consider the following example of code using generics vs using raw usage. Without generics, the type parameters are omitted, but you must explicitly cast whenever an element is extracted from the list.
Expand Gist Expand Code Snippet
- In fact, the bytecode compiled from the two sources above will be identical. We say that generics are implemented by erasure, because the types List<Integer>, List<String>, and List<List<String>> are all represented at runtime by the same type - List. We also use erasure to describe the process that converts the first program to the second program.
- Note that this is not how it is implemented in other languages, as mentioned in the SO answer here. .NET generics actually create new types - a List<String> in C# is a different type than a List<Int> . In Java, under the covers, they are the same thing. - a List<Object>. This means that if you have one of each, you can't look at them at runtime and see what they were declared as - only what they are now.
- The term erasure is a slight misnomer (a wrong or inaccurate use of a name or term) because although the process erases type parameters, it introduces casts. Hence, generics implicitly performs the same cast that is done explicitly when we are not using generics. The guarantee is that the implicit casts added by generics never fail. The fine-print on the guarantee is that it applies only when no unchecked warnings have been issued by the compiler (?).
- A consequence of implementing generics by erasure is that array types differ in key ways from its parameterized types. Executing new String[size] allocates an array, and stores in that array an indication that it's components are of type String. (Note that here they are talking about storing the type in the byte-code/code available during runtime rather than the code at compile time). In contrast, executing new ArrayList<String>() allocates a list, but does not store in the list any indication of the type of its elements. In the jargon we say that, Java reifies array component types but does not reify list element types (or other generic types).
- Also note that type parameters can only be bound to reference types, and not to primitive types. What this means is that you can declare a List<Integer> but not of List<int>.
Boxing and Unboxing
- Every type in java is either a reference type or a primitive type. A reference type is any class, interface, or array type. All reference types are subtypes of class Object, and any variable of the reference type can be set to null. All eight primitive types in java have corresponding class of a reference type.
- Conversion of a primitive type to the corresponding reference type is called boxing and conversion of the reference type to the corresponding primitive type is called unboxing.
- One subtlety of boxing and unboxing is that == is defined differently on primitive and reference types. On type int, it is defined by the equality of values, and on type Integer, it is defined by object identity.
- Consider the following example:
Expand Gist Expand Code Snippet
- Another subtlety to keep in mind is that boxed values can be cached. Caching is required when boxing an int or short between -128 and 127, a char value between '\u0000' and '\u007f', a byte, or a boolean.
- This leads to the following scenario. Taking the same code example as above, we now calculate the sum of 1,2,3,4. We compare the results using the calculateIntegerSum, but now we see that it prints that the two results are equal, as opposed to the above case where we got the result as false. This is because 10 is smaller than 128, so boxing the value 10 always returns exactly the same object. In general, it is not specified whether boxing the same value twice should return identical or distinct objects, so the inequality assertion shown earlier may either fail or succeed depending on the implementation.
Expand Gist Expand Code Snippet
Generic Methods
- Here is a method that accepts an array of any type and converts it into a List. The method convertArraysToList accepts an array of type T[] and returns a list of type List<T>, and does so for any type T . This is indicated by writing <T> at the beginning of the method signature, which declares T as a new type variable. A method which declares a type variable in this way is called a generic method. The scope of the type variable T is local to the method itself. T may appear in the method signature and the method body, but not outside the method.
Expand Gist Expand Code Snippet

Chapter 2: Subtyping and Wildcards

Links to go through
- https://stackoverflow.com/questions/3290261/java-generics-required-capture67-of
- https://stackoverflow.com/questions/11499989/java-generics-capture-list
- https://stackoverflow.com/questions/11500385/how-does-the-jls-specify-that-wildcards-cannot-be-formally-used-within-methods
- https://stackoverflow.com/questions/5361513/reference-is-ambiguous-with-generics
- https://stackoverflow.com/questions/60798067/required-type-capture-of-provided-t
- https://stackoverflow.com/questions/40217285/java-generics-capture-of
Subtyping
- In java, one type is a subtype of another if they are related by an implements or extends clause. Here are some examples. The presence of the same type parameter E in the below examples means that the relations hold only if the same type parameters are used in both lhs and rhs of a row. So if the E on the rhs is Number, the E on the lhs HAS to be Number as well. It cannot be Integer or Double.
Integer is a subtype of Number
Double is a subtype of Number
ArrayList<E> is a subtype of List<E>
List<E> is a subtype of Collection<E>
Collection<E> is a subtype of Iterable<E>
- But also note that:
List<Integer> is NOT a subtype of List<Number>
List<Integer> IS a subtype of List<? extends Number>
List<Object> IS a subtype of List<? super Number>
Integer[] IS a subtype of Number[]
- Subtyping is transitive, meaning that if one type is a subtype of a second, and the second is a subtype of a third, then the first is a subtype of the third. What this means is, List<E> is a subtype of Collection<E>, Collection<E> is a subtype of Iterable<E>, hence List<E> is a subtype of Iterable<E>.
- If one type is a subtype of another, we also say that the second is a supertype of the first.
- Every reference type is a subtype of Object, and Object is a supertype of every reference type. We also say, trivially, that every type is a subtype of itself.
Substitution principle
- A variable of a given type may be assigned a value of any subtype of that type, and a method with a parameter of a given type may be invoked with an argument of any subtype of that type. What this means is that wherever a value of one type is expected, we can provide a value of any subtype of that type.
- Take the Collection class for example which has a method add which takes a parameter of type E. The substitution principle says that if we have a List<Number>, we can add a Decimal or an Integer to it. This is because Decimal and Integer are subtypes of Number.
Expand Gist Expand Code Snippet
- Like we mentioned in the table above, it may seem reasonable to expect that since Integer is a subtype of Number, it follows that List<Integer> is a subtype of List<Number>. But this is NOT the case. Consider the following example. For the same reason, we cannot consider List<Number> to be a subtype of List<Integer> either.
Expand Gist Expand Code Snippet
- So List<Integer> is not a subtype of List<Number>, nor is List<Number> a subtype of List<Integer>; all we have is the trivial case, where List<Integer> is a subtype of itself, and we also have that List<Integer> is a subtype of Collection<Integer>.
- Arrays behave quite differently though. An Integer[] IS a subtype of Number[].
Wildcard with extends
- Another member in the Collection interface is addAll. It adds all the members of one collection to another collection. This is what the method on the interface looks like:
Expand Gist Expand Code Snippet
- Clearly, given a collection of type E, it is ok to add another collection with elements of type E.
- The quizzical phrase ? extends E means that it is also OK to add all members of a collection with elements of any type that is a subtype of E. The ? is called a wildcard, since it stands for some type that is a subtype of E. If the method signature for addAll had been written without the wildcard, then the calls to add lists of integers and doubles to a list of numbers would not have been permitted; you would only have been able to add a list that was explicitly declared to be a list of numbers.
Expand Gist Expand Code Snippet
- We can also use wildcards when declaring variables. Consider the below example. Note the line that is now producing the compile error. It is different from the line that was producing the compile error in the substitution code example we saw earlier. Earlier, it was the fourth line that was throwing the error, because List<Integer> could not be assigned to List<Number>. And the fifth line was fine, since 3.14 is of type Double, we could add it to a List<Number>. However, now the fourth line is fine because List<Integer> is a subtype of List<? extends Number>, but the fifth line causes a compile error, because you cannot add a Double to a List<? extends Number>, since it might be a list of some other subtype of Number. Because, similar to the argument we made during the substitution example, if the line that is producing the compile error actually compiled, then we would have ended up adding a double value to extendedNumber which is actually pointing to the same reference of the List<Number> integers, and hence we would have added a double to a List<Integer>, and that would have created a black hole.
- In general, if a structure contains elements with a type of the form ? extends E, we can get elements out of the structure, but we cannot put elements into the structure. To put elements into a structure we need another kind of wildcard, that we are going to see in the next section.
Expand Gist Expand Code Snippet
Wildcard with super
- Here is a method that copies into a destination list, elements of all the elements of the source.
- The quizzical phrase ? super T means that the destination list may have elements of any type that is a supertype of T, just as the source list may have elements of any type that is a subtype of T.
Expand Gist Expand Code Snippet
- The method copy itself could have been declared with several different possible signatures:
Expand Gist Expand Code Snippet
The Get and Put Principle
- It may be good practice to insert wildcards whenever possible, but how do you decide which wildcard to use? Where should you use extends, where should you use super, and where is it inappropriate to use a wildcard at all? We use the Get and Put principle to determine which is appropriate.
- The principle states that: use an extends wildcard when you only get values out of a structure, use a super wildcard when you only put values into a structure, and don't use a wildcard when you both get and put.
- We already saw this principle at work in the signature of the copy method above. The method gets value out of the source source, so it is declared with an extends wildcard. And it puts values into the destination destination, hence it is declared with the super wildcard.
Expand Gist Expand Code Snippet
- When you use an iterator over a collection, you are effectively getting values out of a structure. Hence you use an extends wildcard. For example, here is a method that takes a collection of numbers, converts each into a double, sums them up and returns the answer in the form of a double. Here we are looking at the case when we are not using the ? extends Number in the parameter of the method. Hence we can only call the method with List<Number>. The others generate compile error. This should not surprise you any more.
Expand Gist Expand Code Snippet
- Now when we actually use the ? extends Number in the method declaration, we can pass in List<Integer> and List<Double> as well.
Expand Gist Expand Code Snippet
- On the other side, whenever we use the add method on a collection, we put values into a structure, so we use a super wildcard. Here is a method that takes a collection of Integers, an integer n, and puts the numbers from 1 to n into the collection. We start with the method declaration not having ? super Integer in the method declaration. As expected, compile fails when trying to call the count method with anything other than Collection<Integer>.
Expand Gist Expand Code Snippet
- Now we add ? super Integer to the method declaration. Again as expected, all the three method calls now compile.
Expand Gist Expand Code Snippet
- Whenever you both put values into and get values out of the same structure, you should not use a wildcard. In the following example, the collection is passed to both sum and count. Hence, the type parameter should Collection<? extends Number> and Collection<? super Integer>. Hence the method declaration can only be either Collection<Number> or Collection<Integer>. We went with Collection<Number>. Since there is no wildcard, the argument must be a collection of Number.
Expand Gist Expand Code Snippet
- The Get and Put Principle also works the other way around. If an extends wildcard is present, pretty much all you will be able to do is get but not put values of that type; and if a super wildcard is present, pretty much all you will be able to do is put but not get values of that type.
Expand Gist Expand Code Snippet
- Each of the rules in the Get and Put principle have one exception to each of them.
- You cannot put anything into a type declared with an extends wildcard - except for the value null, which belongs to every reference type.
- Similarly, you cannot get anything out from a type declared with a super wildcard - except for a value of type Object, which is a supertype of every reference type.
- You may find it helpful to think of ? extends T as containing every type in an interval bounded by the type of null below and by T above (where the type of null is a subtype of every reference type). Similarly, you may think of ? super T as containing every type in an interval bounded by T below and by Object above.
Expand Gist Expand Code Snippet
- It is tempting to think that an extends wildcard ensures immutability, but it does not. As we saw earlier, given a list of type List<? extends Number>, you may still add null values to the list. You may also remove list elements (using remove, removeAll, or retainAll) or permute the list (using swap, sort, or shuffle in the convenience class Collections). If you want to ensure that a list cannot be changed, use the method unmodifiableList in the class Collection.
Arrays
- In Java, array subtyping is covariant, meaning that type S[] is considered to be a subtype of T[] whenever S is a subtype of T.
- The below example compiles without any errors. It is only when you try to run the program that you get a ArrayStoreException. So what causes the error?
- When an array is allocated (as on the first line), it is tagged with its reified type (a run-time representation of its component type, in this case, Integer). And every time an array is assigned into (as on the third line), an array store exception is raised if the reified type is not compatible with the assigned value (in this case, a double cannot be stored into an array of Integer).
Expand Gist Expand Code Snippet
- In contrast, the subtyping relation for generics is invariant, meaning that type List<S> is not considered to be a subtype of List<T>, except in the trivial case where S and T are identical. We have seen this already, here is the above example, but now using a List. Hence, while using List we are able to detect the problem at compile-time itself.
Expand Gist Expand Code Snippet
- Wildcards reintroduce covariant subtyping for generics, in that type List<S> is considered to be a subtype of List<? extends T> when S is a subtype of T.
Expand Gist Expand Code Snippet
- Wildcards also introduce contravariant subtyping for generics, in that type List<S> is considered to be a subtype of List<? super T> when S is a supertype of T (as opposed to a subtype). Arrays do not support contravariant subtyping.
- Choose Collections over arrays because collections are more flexible and they provide many more methods compared to the standard array. On the other hand, arrays of primitive type are much more efficient since they don't involve boxing; and assignments into such an array need not check for an array store exception, because arrays of primitive type do not have subtypes. And despite the check for array store exceptions, even arrays of reference type may be more efficient than collection classes with the current generation of compilers, so you may want to use arrays in crucial inner loops. But this might change in the future(?).
- In some sense, covariant arrays are an artifact of the lack of generics in earlier versions of Java. Once you have generics, covariant arrays are probably the wrong design choice, and the only reason for retaining them is backward compatibility.
- Wow. For many purposes, it may be sensible to consider arrays a deprecated type.
Wildcards Versus Type Parameters
- Consider the following two methods on the Collection interface: contains and containsAll.
- The contains method is defined as follows: boolean contains(Object o);
- The containsAll method is defined as follows: boolean containsAll(Collection<?> c);
- The first method does not even use generics. What this means is that it is perfectly legal code to search for a String in a List<Integer> for example.
-

The second example, containsAll introduces something new. The abbreviated type Collection<?> stands for Collection<? extends Object>. Extending Object is one of the most common uses of wildcards, so it makes sense to provide a short form for writing it.


Expand Gist Expand Code Snippet
- You could rewrite the Collection interface to make use of type parameters instead of wildcards (as we did in the above example).
- So now we can check whether a list of objects contains a list of integers, but not the other way around. This option of using types should be the preferred one, and not the one that the JDK library uses.
Expand Gist Expand Code Snippet
Wildcard Capture
- When a generic method is invoked, the type parameter may be chosen to match the unknown type represented by a wildcard. This is called wildcard capture. (Question: What? Basically means we are going to replace the wildcard ? with a type parameter T)
- Consider the method reverse in the Collections class that accepts a List of any type and reverses it. It has the following two method signatures that are equivalent:
a) public static void reverse(List<?> list);
b) public static void <T> reverse(List<T> list);
- The library uses the wildcard one. Let's see the difference in the implementation of the two method signatures.
Expand Gist Expand Code Snippet
- Another reason to know about wildcard capture is that it can show up in error messages. In general, each occurrence of a wildcard is taken to stand for some unknown type. If the compiler prints an error message containing this type, it is referred to as capture of ?. Hence, if you see the quizzical phrase capture of ? in an error message, it will come from a wildcard type. Even if there are two distinct wildcards, the compiler will print the type associated with each as capture of ?. Bounded wildcards generate names that are even more long-winded, such as capture of ? extends Number.
- Question: How does method overloading work with wildcards/generics?
Restrictions on Wildcards
- Wildcards may not appear at the top level in class instance creation expressions (new), in explicit type parameters in generic method calls, or in supertypes (extends and implements).

Instance Creation

: In a class instance creation expression, if the type is a parameterized type, then none of the type parameters may be wildcards. Only top-level parameters in instance creation are prohibited from containing wildcards. Nested wildcards are permitted.
- This restriction of not being able to instantiate classes with wildcard types was necessry because the Java designers had in mind that every wildcard type is shorthand for some ordinary type, so they believed that ultimately every object should be created with an ordinary type.
- You can think of the relation between wildcard and ordinary types as the relation between interface and classes. You cannot instantiate interfaces, can you? So you cannot instantiate wildcard types either.
Expand Gist Expand Code Snippet

Generic Method Calls

: If a generic method call includes explicit type parameters, those type parameters must not be wildcards.
Expand Gist Expand Code Snippet

Supertypes

: When a class instance is created, it invokes the initializer for its supertype. Hence, any restriction that applies to instance creation must also apply to supertypes. In a class declaration, if the supertype or any superinterface has type parameters, these types must not be wildcards.
Expand Gist Expand Code Snippet
- Lmao get rekt noob.

Chapter 3: Comparison and Bounds

- In this chapter, we will be looking at bounds on types.
Links to go through
- Incompatible equality constraint
- Generic method performs implicit cast while non-generic method needs explicit cast
- Why is generic of a return type erased when there is an unchecked conversion of a method parameter in Java 8?
Comparable
- The interface Comparable<T> contains a method that can be used to compare one object to another.
- Why do I remember already doing this somewhere else? Here is what the Comparable interface looks like.
- The compareTo method returns a value that is negative, zero, or positive depending upon whether the argument is less than, equal to, or greater than the given object. When a class implements Comparable, the ordering specified by this interface is called the natural ordering for that class.
Expand Gist Expand Code Snippet
- Typically, an object belonging to a class can only be compared to another object belonging to the same class. For instance, both the Integer and the String class implement the Comparable interface, and hence you can compare one integer to another, but not one string to another integer. Just for reference, this is what the signature for String and Integer class looks like:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence
public final class Integer extends Number implements Comparable<Integer>
public abstract class Number implements java.io.Serializable
- Also note that, you cannot compare Integer to a Number
Expand Gist Expand Code Snippet
- There is the concept of natural ordering being consistent with the equals method. What this means is that the following statement should hold true: x.equals(y) iff x.compareTo(y) == 0.
- This becomes important when you are making use of collection such as SortedSet or SortedMap. Check the SortedSet example on the LeetCode page here. When we pass in a custom comparator to the sorted set, we see that the string "Eve" is not added to the set because "Bob" was already added. This is because we passed in a custom comparator, that uses the length of two strings to check for equality. It sees that "Eve" has the same length as "Bob", and decides that the two strings are "equal", and hence does not add "Eve" to the set. Clearly, if you did "Eve".equals("Bob"), you would get false as the result. Hence, this is an instance of the compareTo being inconsistent with the equals. This does not seem to be necessarily a bad thing in this case, because we are passing in a custom comparator. But when we are trying to decide a natural ordering of a class, by making the class implements the Comparable interface, we want to be careful that the compareTo is consistent with the equals method that is defined in the class. Later, we will be taking a look at another sample class where the equals and compareTo are inconsistent, meaning, compareTo returns 0 on comparing two objects (implying that they are equal), but if you compared the two objects using the equals implementation of the class, the equals method would return false.
- Comparison differs from equality in that is does not accept a null argument. If x is not null, x.equals(null) must return false, while x.compareTo(null) must throw a NullPointerException.
- Text goes on to discuss the contract of implementing a Comparable interface.
Maximum of a Collection
- Here we have a generic method that declares a bound on the type variable. The method max takes a collection of type Collection<T> and returns a T, and it does this for any type T such that T is a subtype of Comparable<T>.
- The phrase in angle brackets at the beginning of the type signature declares the type variable T, and we say that T is bounded by Comparable<T>. In this case, the bound is recursive, in that the bound on T itself depends upon T.
- As with wildcards, bounds for type variables are always indicated by the keyword extends, even when the bound is an interface rather than a class, as is the case here.
-

Unlike wildcards, type variables must always be bounded using extends, never super.


- Note the error on using the > operator. You can read up about what is causing this on SO here.
Expand Gist Expand Code Snippet
-

Signatures for methods should be as general as possible to maximize utility. If you can replace a type parameter with a wildcard then you should do so.


- We improve the signature of max by replacing <T extends Comparable<T>> T max(Collection<T> coll) with <T extends Comparable<? super T>> T max(Collection<? extends T> coll)
- Following the Get and Put Principle, we use extends with Collection because we get values of type T from the collection, and we use super with Comparable because we

put value of type T into the compareTo method

. In the next section, we'll see an example that would not type-check if the super clause above was omitted.
-

Add example code that shows what is the problem once you have gone through that section???????????????????????????

Fruity Example
- The Comparable interface gives us fine control over what can and cannot be compared. Say, for instance, that we have a Fruit class, that has two subclasses Apple and Orange. Then depending on how we set things up, we can either allow comparison of Apple and Orange, or we may prohibit the comparison of the two. The first example that we are going to look at will allow comparison of Apple and Orange, whereas the second one will not.
- In the first example, each fruit has a name and a size. Two fruits are equal if they have the same name and the same size. Refer the equals method in the below example to verify that that is in fact what we are doing. Following good practice, when you override the equals method, you should also override the hashCode method, as we have done in the examples below.
- When it comes to comparing two objects, we are comparing Fruit based solely on its size and ignoring its name.
- Since Fruit implements Comparable<Fruit>, any two Fruits can be compared. And that is why, we are able to find the max in a list of Fruits that contains both Apple and Orange.
Expand Gist Expand Code Snippet
- Example 2 now. What would you do if you wanted to prohibit the comparison of Apple and Orange?
- The difference between the earlier and this code is that, one, the Apple class now implements the Comparable<Apple> (instead of the Fruit class implementing the interface). This means that an instance of Apple can now ONLY be compared to another instance of Apple. Similarly, for Orange, we implement the Comparable<Orange> interface, and thus making sure that when you call the compareTo method on instances of the Orange class, you can only pass in other instances of Orange class as args.
- Two, note that the code doing the comparison is in the base Fruit class which prevents duplicating the logic in both the Apple and the Orange classes. Also, the method is now marked as protected, so that it can only be called from within the same package, or from other classes that extends the base class that are also outside the package in which the Fruit class is present. Note that we can still directly use internalCompareTo method to compare two instances of Fruit, but that is not the intended way that we want this method to be used.
- Also, just so you can recall, this is a confusion that you had for which you asked the question on SO.
Expand Gist Expand Code Snippet
- The method declaration of the max method looks like this: public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll). We were in the process of understanding the recursive type that is used in the method declaration by forming it ourselves in the FindingMax code example in the "Maximum of a Collection" section above. We reached upto forming this method signature: public static <T extends Comparable<T>> T findMax(Collection<T> collection). So the question now is, why do we need the public static <T extends Comparable<? super T>> T max(Collection<? extends T> coll)
- In the below example we are using the Apple, Orange, and Fruit class from the Example 1 above where we were allowing Apple and Orange to be compared to each other because the Fruit class implemented the Comparable interface.
Expand Gist Expand Code Snippet
- If you tried to do the same thing, but with the Apple, Orange, and Fruit class from the Example 2 where we did not allow Apple to be compared to Orange because the Comparable interface was implemented individually by the child classes, you get the following:
Expand Gist Expand Code Snippet
Comparator
-

Chapter 15: Concepts behind CompletableFuture and Reactive Programming

What are the 4 pillars of Reactive Programming
- Notes have been taken from Venkat presentation.
  • Elasticity

    :
    How many threads should I create?
    There are 2 scenarios -
    a) If your task is computation intensive, then the number of threads that you create should be <= the number of cores in you system.
    b) If your task is IO intensive, then in that case your number of threads should be
    # of threads <= # of cores / (1 - blocking factor)
    The point is that it is incorrect to assume that the number of threads depends on the memory.
    Ok, so what if my program is doing IO operations on multiple threads? How do I go about calculating the ideal number of threads then?
    What is blocking factor supposed to be?
    - ???
  • Message-Driven

    :
    THe idea is that you should never share database. That is if you have multiple microservices taht want to access the database, you should export the data from the database and make it available to the microservice instead of having them individually access the DB instead.
  • Responsive

    :
    - Infinite-scrolling is an example. You can amortize the cost of fetching a page by fetching the page in the background while the user is scrolling.
  • Resilience

    :
    - Fail task successfully.
    - Add circuit-breakers to your application/allow partial-access to the app if some data is not reachable
  • - Reactive programming is functionalProgramming++. It builds on functional composition and lazy evaluation and takes the abstraction even further.
    Concurrency vs Parallelism
    - Fork/Join Frameworks and Parallel Streams are examples of Parallelism. They divide a task into multiple sub-tasks and perform those sub-tasks on different cores, CPUs, or even machines.
    - Conversely, when you are dealing with concurrency, you are trying to perform multiple loosely-related tasks on the same CPU. The objective being to keep the core as busy as possible to maximize the throughput of your application. You want to avoid blocking a thread and wasting its computational resources while waiting (potentially for quite a while) for a result from a remote service or from interrogating a database.
    - Concurrency is a programming property (overlapped execution) that can occur even for a single-core machine, whereas parallelism is a property of execution hardware (simultaneous execution).
    Thread_States
    Evolving Java support for expressing concurrency
    - Terms: Java had locks (via synchronized classes and methods), Runnables, and Threads. The ExecutorService interface extends the Executor interface with the submit method to run a Callable; the Executor interface merely has an execute method for Runnables. Hence, ExecutorService can execute both Runnables and Callables. Callable<T> and Future<T>, which produced higher-level and result-returning variants of Runnable and Thread and used generics.

    What is the difference between Callable and Runnable?


    - SO Link
    - Java 9, provided explicit support for distributed asynchronous programming. (How?)
    - A process can request that the operating system allocate it one or more threads. Each core can be used for one or more processes or threads, but if your program doesn't use threads, it's effectively using only one of the processor cores.
    - My task manager shows that I have 4 cores (8 logical processors), but 4400+ threads running currently. How is this possible? The number of operating system (and Java) threads will significantly exceed the number of hardware threads, so all the hardware threads (We'd use the word core here, but CPUs like the Intel i7-6900K have multiple hardware threads per core) can be usefully occupied executing code even when some operating-system threads are blocked or sleeping. Each core would be able to execute one thread simultaneously. So if there are 30 threads and 4 cores, 26 threads will be waiting to get context switched to get executed. Something like, thread 1-4 runs for 200ms and then 5-8 runs for 200 ms and so on. A single core can also support multiple threads.
    - See also this difference between software threads, hardware threads, and java threads.
    - Note that the JVM runs on top of a native OS, and that the JVM specification does not specify what model to use for mapping Java threads to kernel threads. This decision is JVM implementation dependant, and may be one-to-one, many-to-many, or many to one.. (On a UNIX system the JVM normally uses PThreads and on a Windows system it normally uses windows threads.)
    - Java 5 provided the Executor framework and the idea of thread pools as a higher-level idea capturing the power of threads, which allow Java programmers to decouple task submission from task execution.

    So how do I use concurrency in my program?


    - You could manually create new Thread() and then use Callable or Runnable. But then the question is: how many new threads should you create? Remember if you exceed the number of operating system threads that the system is capable of, it would likely cause the application to crash.

    So what should we do instead?


    - Use Thread Pools instead of directly creating a thread.
    - The ExecutorService in Java provides a way to submit a task and then obtain its result later.
    - It uses the ExecutorService newFixedThreadPool(int nThreads) method. This method creates a ExecutorService containing nThreads (often called worker threads) and stores them in a thread pool, from which unused threads are taken to run submitted tasks on a first-come, first-served basis. These threads are returned to the pool when their tasks terminate. So you can submit a large number of tasks to the pool while keeping the total number of threads created to a hardware-appropriate number. Note the wording: The programmer provides a task (a Runnable or a Callable), which is executed by a thread.

    Thread pools are bad though. Why?


    - A thread pool with k threads can execute only k tasks concurrently. Any further task submissions are held in a queue and not allocated a thread until one of the existing tasks completes. This situation is generally good, in that it allows you to submit many tasks without accidentally creating an excessive number of threads, but you have to be wary of tasks that sleep or wait for I/O or network connections.
    - For eg., if you have 20 tasks submitted to a thread pool of size 5, and 3 of those threads in the pool end up waiting/blocking on some kind of I/O op, the remaining 15 tasks in the queue will end up having only 2 threads for their execution.
    - It's even possible to cause deadlock in a thread pool if earlier task submissions or already running tasks, need to wait for later task submissions, which is a typical use-pattern for Futures.
    Threads and higher-level abstractions

    Chapter 11: MultiThreaded Programming

    What are the two types of multitasking
    - Two types:
    • process-based:
      - A process is, in essence, a program that is executing. Thus, process-based multitasking is the feature that allows your computer to run two or more programs concurrently. For example, process-based multitasking enables you to run the Java compiler at the same time that you are using a text editor or visiting a web site. In process-based multitasking, a program is the smallest unit of code that can be dispatched by the scheduler.
      - Processes are heavy-weight tasks that require their own separate address space.
      - Interprocess communication is expensive and limited.
      - Context switching from one process to another is also costly.
    • thread-based:
      - It is the smallest unit of dispatchable code. This means that a single program can perform two or more tasks simultaneously. For example, a text editor can print text at the same time as the text is being formatted, so long as the two tasks are being performed by two different threads.
      - Threads are lighter-weight and require less overhead when compared to process-based multitasking
      - They share the same address space.
      - Interthread communication is inexpensive, and context switching from one thread to another is lower in cost.
    - In process-based multitasking, two or more programs can run at the same time. In thread-based multitasking, two or more tasks from the same program can run simultaneously. - A multithreaded program contains two or more parts that can run concurrently. Each part of such a program is called a thread.
    The Java Thread Model
    - Single threaded applications use an approach called event loop with polling. In general, in a single-threaded environment, when a thread blocks (that is, suspends execution) because it is waiting for some resource, the entire program stops running.
    - The benefit of Java's multithreading is that the main loop/polling mechanism is eliminated. When a thread blocks in a Java program, only the single thread that is blocked pauses. All other threads continue to run.
    - Threads exist in several states. A thread can be running. It can be ready to run as soon as it gets CPU time. A running thread can be suspended, which temporarily halts its activity. A suspended thread can be resumed, allowing it to pick up where it left off. A thread can be blocked when waiting for a resource. At any time, a thread can be terminated, which halts its execution immediately. Once terminated, a thread cannot be resumed.
    Thread Priorities
    - Java assigns to each thread a priority. Thread priorities are integers that specify the relative priority of one thread to another.
    - A thread's priority is used to decide when to switch from one running thread to the next. This is called a context switch.
    - Rules for context switch:
    • A thread can voluntarily relinquish control. This occurs when explicitly yielding, sleeping, or when blocked. In this scenario, all other threads are examined, and the highest-priority thread that is ready to run is given the CPU.
    • A thread can be preempted by a higher-priority thread. In this case, a lower-priority thread that does not yield the processor is simply preempted - no matter what it is doing - by a higher-priority thread. Basically, as soon as a higher-priority thread wants to run, it does. This is called preemptive multitasking.
    The Thread Class and the Runnable Interface
    - To create a new thread, you program will extend the Thread class or implement the Runnable interface.
    The Main Thread
    - main thread is the thread that is executed when when your program begins. The main thread is important for two reasons:
    • It is the thread from which other "child" threads will be spawned.
    • Often, it must be the last thread to finish execution because it performs various shutdown actions.
    Expand Gist Expand Code Snippet
    Creating a Thread
    - You create a thread by instantiating an object of type Thread. This can be done in two ways:
    • You can implement the Runnable interface
    • You can extend the Thread class itself
    Implementing Runnable
    - The Runnable class should be implemented by any class whose instances are intended to be executed by a thread. The class must define a method of no arguments called run.
    - Inside run() you will define the code that constitutes the new thread. After you create a class that implements Runnable, you will instantiate an object of type Thread from within that class.
    - The Thread class defines many constructors. The one we use here is: Thread(Runnable threadObj, String threadName). Here, threadObj is an instance of a class that implements the Runnable interface. This defines where the execution of the thread will begin. The name of the new thread is specified by threadName.
    - After the new thread is created, it will not start running unless you call its start() method. The start() method actually calls the run() method of the class that is referenced by threadObj.
    class PrimeRun implements Runnable {
    long minPrime;
    PrimeRun(long minPrime) {
    this.minPrime = minPrime;
    }
    public void run() {
    // compute primes larger than minPrime
    }
    }
    The following code would then create a thread and start it running:
    PrimeRun p = new PrimeRun(143);
    new Thread(p).start();
    //or
    Thread t = new Thread(p);
    t.start();
    - Passing this as the first argument indicates that you want the new thread to call the run() method on this object. Inside main(), start() is called, which starts the thread of execution beginning at the run() method. This causes the child thread's for loop to begin. Next the main thread enters its for loop. Both threads continue running, sharing the CPU in single-core systems, until their loops finish.
    Expand Gist Expand Code Snippet
    Extending Thread
    - The second way to create a thread is to create a new class that extends Thread, and then to create an instance of that class. The extending class must override the run() method, which is the entry point for the new thread. As before, a call to start() begins execution of the new thread.
    class PrimeThread extends Thread {
    long minPrime;
    PrimeThread(long minPrime) {
    this.minPrime = minPrime;
    }
    public void run() {
    // compute primes larger than minPrime
    }
    }
    The following code would then create a thread and start it running:
    PrimeThread p = new PrimeThread(143);
    p.start(); -
    Expand Gist Expand Code Snippet
    - What's the difference between start() and run()
    - Well if you defined the NewThread class as: calling run() is literally going to call the run() method, like a literal method call. No new thread is going to be created. So in the example above, if you wrote newThread.thread.run() on Line 32, there would be a method call to the run() method. The run() method would finish executing. And only after that would the execution of the loop in te Main class even start. Only if you use the start() method is a new thread created and the code inside the run() method executed.
    - Another difference between start() and run() in Java thread is that you can not call start() twice. Once started, second start() call will throw IllegalStateException in Java while you can call run() method several times since it's just an ordinary method.

    - When should you use Runnable vs when should you use Thread?.
    - Almost always you will be using the MyThread implements Runnable interface to create a new thread.
    - Classes should be extended only when they are being enhanced or adapted in some way. So, if you will not be overriding any of Thread's other methods, it is probably best simply to implement Runnable. Also, by implementing Runnable, your thread class does not need to inherit Thread, making it free to inherit a different class. //TODO: Go through this link for description of concurrency.

    - Why do you need a MyThread extends Thread way of creating threads?
    - Because sometimes (almost never, but sometimes) you want to be able to change the basic behaviour of Thread. That's when you'll need to extend it. You can change it by overriding a method from the Thread class, you can't do it by implementing one from Runnable.
    - Oracle link explaining how you would create and use a new Thread by extending Thread or by implementing Runnable
    Creating Multiple Threads
    - Your program can spawn as many threads as you need.
    - In the below example we are creating multiple threads. In the printout, note where the Main thread is exiting. It is not like Main is waiting for the other threads to end.
    Expand Gist Expand Code Snippet
    Using isAlive() and join()
    - Look at the previous example. The main thread finished ealrier than the child threads. Often, you would want the main thread to finish last.
    - Two ways exist to determine whether a thread has finished or not. First, you can call isAlive() on the thread which returns true if the thread is still running.
    - But you should prefer the join() method. This method waits until the thread on which it is called terminates. It's name comes from the concept of the calling thread waiting until the specified thread joins it. join also allows you to specify a maximum amount of time that you want to wait for the specified thread to terminate.
    • void join(): Waits for this thread to die.
    • void join(long millis): Waits at most millis milliseconds for this thread to die.
    • void join(long millis, int nanos): Waits at most millis milliseconds plus nanos nanoseconds for this thread to die.
    - In the below example, remember that the main thread that is calling mt1.join (and others) will wait for the mt1 to finish. The mt2 thread is running in parallel and is not affected by the mt1 and mt1.join() method calls at all. StackOverflow Link
    Expand Gist Expand Code Snippet
    Thread Priorities
    - Thread priority is just a hint to OS task scheduler and is dependent on the underlying OS. OS will try to allocate more resources to a high priority thread but it does not guarantee it. So if your program is dependent on thread priorities than you are in-turn binding your program to underlying OS, which is bad.
    - From Java Concurrency in Practice: Avoid the temptation to use thread priorities, since they increase platform dependence and can cause liveness problems. Most concurrent applications can use the default priority for all threads. Link to post on SO
    Synchronization
    - When two or more threads need access to a shared resource, they need some way to ensure that the resource will be used by only one thread at a time. The process by which this is achieved is called synchronization.
    - Key to synchronization is the concept of the monitor. A monitor is an object that is used as a mutually exclusive lock. Only one thread can own a monitor at a given time. When a thread acquires a lock, it is said to have entered the monitor. All other threads attempting to enter the locked monitor will be suspended until the first thread exits the monitor. These other threads are said to be waiting for the monitor. A thread that owns a monitor can reenter the same monitor if it so desires.
    - SO Link explaining what a monitor actually is
    - This is what happens when your code is NOT synchronized.
    Expand Gist Expand Code Snippet
    - By calling sleep(), the call() method allows execution to switch to another thread. This results in the mixed-up output of the three message strings. In this program, nothing exists to stop all three threads from calling the same method, on the same object, at the same time. This is known as a race condition, because the three threads are racing each other to complete the method.
    Using synchronized methods
    - To prevent the above, you need to serialize the access to the method call(). That is, you must restrict its access to only one thread at a time. To do this, you simply need to precede call()'s definition with the keyword synchronized.
    class CallMe{
    synchronized void callMe(){...}
    }
    - This prevents other threads from entering the method call() when another thread is already using it. And after we make this change, we get the correct output:
    [Hello]
    [World]
    [Synchronized]
    Example of using the synchronized statement:
    Expand Gist Expand Code Snippet
    Well we would have expected "Hello Synchronized World". But threads gonna thread I guess.
    Any time that you have a method, or group of methods, that manipulates the internal state of an object in a multithreaded situation, you should use the synchronized keyword to guard the state from race conditions. Remember, once a thread enters any synchronized method on an instance, no other thread can enter any other synchronized method on the same instance. However, nonsynchronized methods on that instance will continue to be callable.
    Using synchronized Statements
    - Creating synchronized methods within classes might not always work.
    - Imagine that you want to synchronize access to objects of a class that was not designed for multithreaded access. That is, the class does not use synchronized methods. Further, this class was not created by you, but by a third party, and you do not have access to the source code. Thus, you can't add synchronized to the appropriate methods within the class. How can access to an object of this class be synchronized?
    - You put calls to the methods defined by the class inside a synchronized block.
    - This is the general form of the synchronized statement:
    synchronized(objRef){
    //Statements to be synchronized
    }
    Here objRef is the reference to the object being synchronized. A synchronized block ensures that a call to a method that is a member of objRef's class occurs only after the current thread has successfully entered objRef's monitor.
    - The previous example can then be rewritten in the following manner:
    Expand Gist Expand Code Snippet
    - Why do we get the warning on line 30?
    Interthread Communication
    - //TODO: Read up on what Polling is
    - In Java , you have wait(), notify(), and notifyAll() methods. These methods are implemented as final methods in Object, so all classes have them. All 3 methods can be called only from within a synchronized context.
    • notify():
      - Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object's monitor by calling one of the wait methods.
      - The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object. The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.
      - This method should only be called by a thread that is the owner of this object's monitor. A thread becomes the owner of the object's monitor in one of three ways:
      • By executing a synchronized instance method of that object.
      • By executing the body of a synchronized statement that synchronizes on the object.
      • For objects of type Class, by executing a synchronized static method of that class.
      - Only one thread at a time can own an object's monitor.
    • notifyAll:
      - Wakes up all threads that are waiting on this object's monitor. A thread waits on an object's monitor by calling one of the wait methods. The awakened threads will not be able to proceed until the current thread relinquishes the lock on this object. The awakened threads will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened threads enjoy no reliable privilege or disadvantage in being the next thread to lock this object.
      - This method should only be called by a thread that is the owner of this object's monitor. See the notify method for a description of the ways in which a thread can become the owner of a monitor.
    • wait():
      - Causes the current thread to wait until either another thread invokes the notify() method or the notifyAll() method for this object, or a specified amount of time has elapsed. The current thread must own this object's monitor.
      - This method causes the current thread (call it T) to place itself in the wait set for this object and then to relinquish any and all synchronization claims on this object. Thread T becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:
      • Some other thread invokes the notify method for this object and thread T happens to be arbitrarily chosen as the thread to be awakened.
      • Some other thread invokes the notifyAll method for this object.
      • Some other thread interrupts thread T.
      • The specified amount of real time has elapsed, more or less. If timeout is zero, however, then real time is not taken into consideration and the thread simply waits until notified.
      - The thread T is then removed from the wait set for this object and re-enabled for thread scheduling. It then competes in the usual manner with other threads for the right to synchronize on the object; once it has gained control of the object, all its synchronization claims on the object are restored to the status quo ante - that is, to the situation as of the time that the wait method was invoked. Thread T then returns from the invocation of the wait method. Thus, on return from the wait method, the synchronization state of the object and of thread T is exactly as it was when the wait method was invoked.
    - Code without using any kind of inter-thread communication:
    - The problem with this code is that although the put() and get() methods on Q are synchronized, nothing is stopping the producer from overrunning the consumer, nor will anything stop the consumer from consuming the same queue value twice. Hence you get erroneous output.
    Expand Gist Expand Code Snippet
    - Code after using inter-thread communication:
    - Inside get(), wait() is called. This causes it's execution to suspend until Producer notifies you that some data is ready. When this happens execution inside get resumes. After the data has been obtained get calls notify. This tells the producer that it is ok to put more data in the queue. Inside put(), wait suspends execution until Consumer has removed the item from the queue. When the execution resumes, the next item of data is out in the queue, and notify is called. This tells the Consumer that it should now remove it.
    Expand Gist Expand Code Snippet
    Deadlock
    - A special type of error that you need to avoid that relates specifically to multitasking is deadlock, which occurs when two threads have a circular dependency on a pair of synchronized objects. For example, suppose one thread enters the monitor on object X and another thread enters the monitor on object Y. If the thread in X tries to call any synchronized method on Y, it will block as expected. However, if the thread in Y, in turn, tries to call any synchronized method on X, the thread waits forever, because to access X, it would have to release its own lock on Y so that the first thread could complete. - Code showing how Deadlock can be created:
    - The next example creates two classes, A and B, with methods foo() and bar(), respectively, which pause briefly before trying to call a method in the other class. The main class, named Deadlock, creates an A and a B instance, and then calls deadlockStart() to start a second thread that sets up the deadlock condition. The foo() and bar() methods use sleep() as a way to force the deadlock condition to occur.
    Expand Gist Expand Code Snippet
    Suspending, Resuming, and Stopping Threads
    - A thread must be designed so that the run() method periodically checks to determine whether that thread should suspend, resume, or stop its own execution.
    - Typically, this is accomplished by establishing a flag variable that indicates the execution state of the thread. As long as this flag is set to "running," the run() method must continue to let the thread execute. If this variable is set to "suspend", the thread must pause. If it is set to "stop", the thread must terminate. Of course, a variety of ways exist in which to write such code, but the central theme will be the same for all programs.
    - Apparently this example was supposed to teach me something:
    Expand Gist Expand Code Snippet
    Obtaining a Thread's State
    - You can obtain the current state of a thread by using: getState(). This returns a value of type Thread.State that indicates the state of the Thread at the time the call was made.
    - State is an enumeration that is defined by Thread. These are the values that can be returned by getState().
    Value State
    BLOCKED A thread that has suspended execution because it was waiting to acquire a lock
    NEW A thread that has not begun execution
    RUNNABLE A thread that is either currently executing or will execute when it gains access to the CPU
    TERMINATED A thread that has completed execution
    TIMED_WAITING A thread that has suspended execution for a specified period of time, such as when it has called sleep(). This state is also entered when a timeout version of wait() or join() is called.
    WAITING A thread that has suspended execution because it is waiting for some action to occur. For example, it is waiting because of a call to a non-timeout version of wait() or join().
    Thread_States
    - This is how you can use the Thread.State in your code:
    Thread.State ts = thrd.getState();
    if (ts == Thread.State.RUNNABLE) {//do stuff}

    Chapter 6: Threads

  • What does "Atomic" mean in Programming
  • - Look here.
    - JMM
  • What is the difference between Atomic and Volatile
  • - Look here.
    -
  • How do I make my variables thread-safe?
  • - Link to Baeldung
  • Why should we declare variables to be volatile
  • - Link to SO where the example uses Strings.
  • What is the difference between volatile and atomic
  • - Read on SO here.
  • What is the difference between a live-lock and a dead-lock?
  • - Read on SO here
  • What is the difference between wait and sleep?
  • - Read here on SO.
  • Questions about the lifecycle stages of a thread?
  • - Difference between WAIT and BLOCKED thread states
    - Java thread state transition, WAITING to BLOCKED, or RUNNABLE?
    - Life Cycle of a Thread in Java

    Chapter 28: The Concurrency Utilities

    Parallel Programming via the Join/Fork Framework
    - It is important to point out the distinction between traditional multithreading and parallel programming.
    - In the past, most computers had a single CPU and multithreading was primarily used to take advantage of idle time, such as when a program is waiting for user input. Using this approach, one thread can execute while another is waiting. In other words, on a single-CPU system, multithreading is used to allow two or more tasks to share the CPU. This type of multithreading is typically supported by an object of type Thread (as described in Chapter 11). Although this type of multithreading will always remain quite useful, it was not optimized for situations in which two or more CPUs are available (multicore computers).
    - When multiple CPUs are present, a second type of multithreading capability that supports true parallel execution is required. With two or more CPUs, it is possible to execute portions of a program simultaneously, with each part executing on its own CPU. This can be used to significantly speed up the execution of some types of operations, such as sorting, transforming, or searching a large array. In many cases, these types of operations can be broken down into smaller pieces (each acting on a portion of the array), and each piece can be run on its own CPU.
    The Main Fork/Join Classes
    - At the core of the Fork/Join framework are the following 4 classes:
    Class Description
    ForkJoinTask<V> An abstract class that defines a Task
    ForkJoinPool Manages the execution of ForkJoinTasks
    RecursiveAction A subclass of ForkJoinTask<V> for tasks that do not return value
    RecursiveTask<V> A subclass of ForkJoinTask<V> for tasks that return values
    1) ForkJoinTask<V>
    -

    Chapter ?: Design Patterns

    Singleton Pattern
    - Something about Double Checked Locking (DCL) here on WikiPedia.
    -