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>>
).
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, theT
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, doingBox box = new Box();
is a raw usage of Box<T>. In this case, box would just be a box of Object
s. Number
or its subclasses. This is what bounded type parameters are for. Number
? class MyClassName <T extends T1 & T2 & T3>
class A {/* ... */}
interface B {/* ... */}
interface C {/* ... */}
class D <T extends A & B & C> {/* ... */};
Integer
is a subtype of Number
, List<Integer>
is not a
subtype of List<Number>
. The below code snippet provides an example of this:
public <T extends SomeBaseClass> void myMethod(Class<T> clz)
vs
public void myMethod(Class<? extends SomeBaseClass> clz)
ObjectWrapper
with String, and want Java to pre-emptively
warn us
when we try to use it with Integer
type. <T>
with String
instead.
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. Wrapper<String>
is not assignment compatible to Wrapper<Object>
. 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.
Object
as
parameter type seemed to be more suitable. (Not using T
as a parameter type right now. Probably come back to that later.)
Wrapper<String>
and
Wrapper<Object>
are not assignment compatible. <?>
. 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. 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. String str = unknownWrapper.getRef();
, the compiler is going to
complain and say: 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();
.
null
(Source on DZone). <? 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>
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). <? super T>
. This means "anything that is of type T
or is a supertype of T
is acceptable". 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.
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. 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.
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
.
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.
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. 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.
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). List<Integer>
but not of List<int>
.
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. ==
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. int
or short
between -128 and 127, a
char
value between '\u0000'
and '\u007f'
, a byte
, or a boolean
. 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.
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> |
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[] |
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>
. Object
, and Object
is a supertype of every reference type. We also say, trivially, that every type is a
subtype of itself.
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
.
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.
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>
. Integer[]
IS a subtype of Number[]
. extends
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:
E
, it is ok to add another collection with elements of type E
. ? 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.
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. ? 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.
super
? 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
. 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. 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. extends
wildcard. And it puts values into the destination destination, hence it is declared with the super
wildcard.
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.
? extends Number
in the method declaration, we can pass in List<Integer>
and List<Double>
as well.
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 Integer
s, 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>
.
? super Integer
to the method declaration. Again as expected, all the three method calls now compile.
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
.
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.
extends
wildcard - except for the value null
, which belongs to every reference type. super
wildcard - except for a value of type Object
, which is a supertype of
every reference type. ? 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.
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.
S[]
is considered to be a subtype of T[]
whenever S
is a subtype of
T
. ArrayStoreException
. So what causes the error? 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
).
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.
List<S>
is considered to be a subtype of List<? extends T>
when
S
is a subtype of T
.
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. Collection
s over array
s 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(?). Collection
interface: contains
and containsAll
. contains
method is defined as follows: boolean contains(Object o);
containsAll
method is defined as follows: boolean containsAll(Collection<?> c);
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.
Collection
interface to make use of type parameters instead of wildcards (as we did in the above example). ?
with a type parameter T
) 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: public static void reverse(List<?> list);
public static void <T> reverse(List<T> list);
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
. 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.Generic Method Calls
: If a generic method call includes explicit type parameters, those type parameters must not be wildcards.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.Comparable<T>
contains a method that can be used to compare one object to another. Comparable
interface looks like. 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. 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
Integer
to a Number
equals
method. What this means is that the following statement should hold true:
x.equals(y)
iff x.compareTo(y) == 0
. 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. x.equals(null)
must return false, while
x.compareTo(null)
must throw a NullPointerException
. Comparable
interface.
Collection<T>
and
returns a T
, and it does this for any type T
such that T
is a subtype of Comparable<T>
. 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
. 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
.
>
operator. You can read up about what is causing this on SO here.
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.
<T extends Comparable<T>> T max(Collection<T> coll)
with
<T extends Comparable<? super T>> T max(Collection<? extends T> coll)
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
super
clause above was omitted. Add example code that shows what is the problem once you have gone through that section???????????????????????????
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. 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. 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.
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. 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. 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)
Comparable
interface.
Comparable
interface was implemented individually by the child classes, you get the following:
Elasticity
:# of threads <= # of cores / (1 - blocking factor)
blocking factor
supposed to be? Message-Driven
:Responsive
:Resilience
:synchronized
classes and methods), Runnable
s, and Thread
s. The ExecutorService
interface extends the Executor
interface with the submit
method to run a Callable
; the Executor
interface merely has
an execute
method for Runnable
s. Hence, ExecutorService
can execute both Runnable
s and Callable
s.
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 how do I use concurrency in my program?
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?
ExecutorService
in Java provides a way to submit a task and then obtain its result later. 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?
Thread
class or implement the Runnable
interface.
Thread
. This can be done in two ways:
Runnable
interfaceThread
class itselfRunnable
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
. 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. 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. 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
}
}
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
//or
Thread t = new Thread(p);
t.start();
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.
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
}
}
PrimeThread p = new PrimeThread(143);
p.start();
-
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.
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.
Runnable
vs when should you use Thread
?.
MyThread implements Runnable
interface to create a
new thread.
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.
MyThread extends Thread
way of creating threads?
isAlive()
and join()
isAlive()
on the thread which returns true if the thread is still running.
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.
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
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.
synchronized
methodscall()
.
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(){...}
}
call()
when another thread is already
using it. And after we make this change, we get the correct output:
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.
synchronized
Statementssynchronized
methods within classes might not always work.
synchronized
block.
synchronized
statement:
synchronized(objRef){
//Statements to be synchronized
}
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.
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()
:
notifyAll
:
wait()
:
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.
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.
run()
method periodically checks to determine whether
that thread should suspend, resume, or stop its own execution.
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.
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.State
in your code: Thread.State ts = thrd.getState();
if (ts == Thread.State.RUNNABLE) {//do stuff}
volatile
String
s.
volatile
and atomic
wait
and sleep
?
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 |