You are on page 1of 9

My java notes - Multi-Threading:

1. If a thread goes to sleep it does not release the lock. But wait() release the lock.
2. synchronized method(){
system.out.println("heello");
}

is same as :

method(){
synchronized(this){
system.out.println("heello");
}
}
benefit of second approach is that its flexible: This way u can have more then one locks for same
object( if u use some third party object for locking instead of this.) u can sync one method using
obj1 and another method using obj2.

3. http://tutorials.jenkov.com/java-concurrency/thread-pools.html
4.
http://www.deitel.com/articles/java_tutorials/20051126/JavaMultithreading_Tutorial_Part4.html

5. A thread can also wake-up without being notified, interrupted, or times out. This is called
spurious wake-up. Though this will occur rarely, your application must guard against spurious
wake-ups.This can be done by testing a condition which can cause wake-up. If condition is not
true then this wake up is spurious one. So make your thread to wait again.

example:

class MyThread extends Thread{

Lock lock = new Lock();


boolean signal = false;

public void doWait(){


synchronized(lock){
while(!signal){
lock.wait();
}
signal = false; // clear signal and continue running... ie. signal is back to initial stage.
}
}

public void doNotify(){


synchronized(lock){
lock.notify();
signal = true;
}
}

}
6. Database deadlocks:

transaction1 request1 locks record1 for update operation.


transaction2 request1 locks record2 for update operation.
transaction1 request2 tries to get lock on record2 for update operation.
transaction2 request2 tries to get lock on record1 for update operation.

7. Deadlock prevention mechanism -


Ordering of locks.

If you make sure that all locks are taken in same order by any thread then deadlock can never
occur. eg:

common deadlock situation:

sync(A) sync(B)
sync(B) sync(A)

make sure all thread acquire locks on this order A and then B.

Lock time out

thread1 while waiting on B times out and release lock on A. So thread2 will get lock on A and
complete its execution.

8. BlockingQueue

This is implementation of a normal queue. Just check boundary conditions and put wait and notify.
if boundary condition for an operation is reached then make it wait. And just before you are
adding/removing call notifyAll. Make sure to call notifyAll only when it is actually required.
notifyAll is required only at boundary conditions.

public class BlockingQueue {

private List queue = new LinkedList();


private int limit = 10;

public BlockingQueue(int limit){


this.limit = limit;
}

public synchronized void enqueue(Object item)


throws InterruptedException {
while(this.queue.size() == this.limit) {
wait();
}
if(this.queue.size() == 0) {
notifyAll();
}
this.queue.add(item);
}

public synchronized Object dequeue()


throws InterruptedException{
while(this.queue.size() == 0){
wait();
}
if(this.queue.size() == this.limit){
notifyAll();
}

return this.queue.remove(0);
}

9. Thread Pool implementation

public class ThreadPool {

private Queue queue;


List<PoolThread> threadList = new ArrayList<PoolThread>();

public ThreadPool (int noOfThreads, int batchSize){


queue = new Queue(batchSize);
for(int i=0; i<noOfThreads; i++){
PoolThread thread = new PoolThread(queue);
thread.setName("thread "+i);
threadList.add(thread);
}

for(PoolThread thread : threadList){


thread.start();
}
}

public void execute(List<Task> taskList){


for(int i=0; i<taskList.size(); i++){
try{
queue.enqueue(taskList.get(i));
}catch(InterruptedException ie){
}
}
}
}

public class PoolThread extends Thread{

Queue queue;
String name;
PoolThread(Queue queue){
this.queue = queue;

public void run(){


while(true){
try{
Task task = (Task)queue.dequeue();
task.run();
}catch(InterruptedException ie){

}
}
}

public class ThreadPoolTest {


private static List<Task> taskList = new ArrayList<Task>();

public static void main(String args[]){


ThreadPool pool = new ThreadPool(5, 10);
for(int i=1; i<=20; i++){
taskList.add(new Task("Task "+i));
}

pool.execute(taskList);
}

class Task implements Runnable{


String name;
public Task(String name){
this.name=name;
}
public void run(){
System.out.println(name+" executed ");
}
}

To stop the ThreadPool we can call this.interrupt(); on every thread in thread pool.

10. Java5 Java.util.concurrent package Executor framework is just like thread pool.

Executor can execute tasks in async fashion.

import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;

public class as
{
public static void main( String[] args )
{
// create and name each runnable
Task task1 = new Task( "task1" );
Task task2 = new Task( "task2" );
Task task3 = new Task( "task3" );
System.out.println( "Starting thread pool" );

ExecutorService threadExecutor = Executors.newFixedThreadPool( 3 );

// start threads and place in runnable state


threadExecutor.execute( task1 ); // start task1
threadExecutor.execute( task2 ); // start task2
threadExecutor.execute( task3 ); // start task3

threadExecutor.shutdown(); // shutdown worker threads

System.out.println( "Threads started, main ends\n" );


} // end main
}

11. Concurrent Colloctions

List list = Collections.synchronizedList(new ArrayList());

This returns a list whose methods are all sync. But dont always rely on this because, it only sync
all methods like add, get etc. individually. All individual operations are thread-safe, but sequences
of operations where the control flow depends on the results of previous operations may be subject
to data races. Other operations like iteration or put-if-absent still require external sync.

synchronized(list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}

Failure to follow this advice may result in non-deterministic behavior.

An example:
// iteration -- contains race conditions
// may require external synchronization

for (int i=0; i<list.size(); i++) {


doSomething(list.get(i));
}

it is possible that at some other location some code is deleting element from list. And if the
timings are bad then that delete operation would execute just after list.size(). In this case,
list.get() is like to return null and doSomething() would potentially throw NPE.

How can you avoid this:

you must lock the entire List while you are iterating by wrapping it with a
synchronized block, synchronizing on the list. This addresses the data race, but
has further costs for concurrency, since locking the entire List while iterating
could block other threads from accessing the list for a long time.

Another example:

// normal iteration -- can throw ConcurrentModificationException


// may require external synchronization
for (Iterator i=list.iterator(); i.hasNext(); ) {
doSomething(i.next());
}

Iterator is used to optimize the performance of iterating.


However, if one thread changes a collection while another thread is traversing it through an
Iterator, the next Iterator.hasNext() or Iterator.next() call will throw
ConcurrentModificationException.

Solution: same as above, synchronize whole block on list object.

Problem in synchronizing on whole list object:

Scalability describes how an application's throughput behaves as its workload and available
computing resources increase. A scalable program can handle a proportionally larger workload
with more processors, memory, or I/O bandwidth. Locking a shared resource for exclusive access
is a scalability bottleneck -- it prevents other threads from being able to access that resource,
even if idle processors are available to schedule those threads. To achieve scalability, we must
eliminate or reduce our dependence on exclusive resource locks.

Final Solution:

java.util.concurrent package

use CopyOnWriteArrayList and ConcurrentHashMap instead of Collections.synchronizedMap


or Collections.synchronizedList.

However these classes should be used only if required otherwise ArrayList and HashMap are still
widely used.

CopyOnWriteArrayList is used when traversal operation is more than write operations and when
you dont want to sync traversal operation.

13. why did Sun depricated .stop() method?

Because it stopped the thread without any possibility to save data. You can simulate .stop()
method following ways:

boolean letStop;
void prepareForStop()
void doStop()

in prepareForStop() you can save your data and set letStop variable to true. and if letStop is true
then call doStop().

14. Daemon threads:

User threads are service provider threads. When the only threads running are daemon threads
jvm exits. For example garbage collector.
Daemon thread should not be used to run your program. Because consider a scenario: Suppose
you are writing data to a file using daemon thread and if all other threads are done then daemon
thread will also stop and data on file will be left corrupted.

Daemon thread should be used in cases where abrupt termination of thread does not cause any
negative impact.

Think of the JVM as a club. Daemon threads are like the bouncers, and User threads are the
people. Until everyone's gone, the bouncers will stay. But once they leave, the bouncers aren't
needed anymore and they leave too. That's what happens in the JVM. User threads stay until
they're done, and once they're done, the JVM terminates any remaining Daemon threads.

a very good example of usage of Daemon thread:

I had a case in which my APP needed to delete some info from my DB each day. I had a thread
like this:

public void run () {


while (true) { //infinite loop
//Delete info from db
//Sleep one day
}
}

The thing is... when I wanted to stop my APP Server, it hanged, because the Thread was a USER
thread (not daemon) and JVM does not stop until all USER threads finish executing... and my
thread was in a infinite loop!

So, for practical purposes, setting the thread as DAEMON tells the JVM that it has permission to
stop this thread if you are shutting down your app.

run() method for a daemon thread is typically an infinite loop that waits for service requests.

Methods are:

setDaemon(true);
isDaemon();

setDaemon should not be called after .start. If you do then it will throw
java.lang.IllegalThreadStateException

15. A good point

Usually in a non threaded environment main is the last thread to finish.(thats the thread JVM
creates for your program.) But if it is spawning multiple thread even though main thread is over,
other threads keep running.

16. Thread.sleep(xxx )

JVM can guarantee that your thread will not wake up before xxx ms, but it is highly likely that
your thread can sleep more than xxx ms.

17. Is there a way to stop a thread :

endThread(){
stop = true
}

run(){
while(stop!){
/// more code
}
}

we have to do something like this.....

18. ThreadLocal :

http://www.javamex.com/tutorials/synchronization_concurrency_thread_local.shtml

When we say :
myTL.set(new Integer(0));// we are basically setting this value in current
// thread's local hashmap. eg. map1.put(myTL, intVal);

---------
http://www.ibm.com/developerworks/java/library/j-threads3.html

Using ThreadLocal to implement a per-thread Singleton

Thread-local variables are commonly used to render stateful Singleton or shared objects thread-
safe, either by encapsulating the entire unsafe object in a ThreadLocal or by encapsulating the
object's thread-specific state in a ThreadLocal. For example, in an application that is tightly tied
to a database, many methods may need to access the database. It could be inconvenient to
include a Connection as an argument to every method in the system -- a sloppier, but
significantly more convenient technique would be to access the connection with a Singleton.
However, multiple threads cannot safely share a JDBC Connection. By using a ThreadLocal in
our Singleton, as shown in Listing 3, we can allow any class in our program to easily acquire a
reference to a per-thread Connection. In this way, we can think of a ThreadLocal as allowing us
to create a per-thread-singleton.

Listing 3. Storing a JDBC Connection in a per-thread Singleton

public class ConnectionDispenser {


private static class ThreadLocalConnection extends ThreadLocal {
public Object initialValue() {
return
DriverManager.getConnection(ConfigurationSingleton.getDbUrl());
}
}

private static ThreadLocalConnection conn = new


ThreadLocalConnection();
public static Connection getConnection() {
return (Connection) conn.get();
}
}
Any stateful or non-thread-safe object that is relatively more expensive to create than to use,
such as a JDBC Connection or a regular-expression matcher, is a good candidate for the per-
thread-singleton technique. Of course, for situations like this, you can use other approaches, like
pooling, for safely managing shared access. However, even pooling has some potential drawbacks
from a scalability perspective. Because pool implementations must synchronize to maintain the
integrity of the pool data structures, if all threads are using the same pool, program performance
may suffer due to contention in a system with many threads accessing the pool frequently.

-----------------

An example may help clarify this concept. A servlet is executed in a thread, but since many users
may use the same servlet at the same time, many threads will be running the same servlet code
concurrently. If the servlet uses a ThreadLocal object, it can hold data local to each thread. The
user ID is a good example of what could be stored in the ThreadLocal object.

--------------------

19. Double check locking

http://en.wikipedia.org/wiki/Double-checked_locking
http://www.ibm.com/developerworks/java/library/j-dcl.html

The IBM article is old one. Now from Java 1.5 onwards double check locking works well with
volatile keyword. earlier versions of java did not have correct implementation of volatile keyword
but 1.5 onwards it works. See head first design pattern book for reference.