Threads

22) Write code to define instantiate and start new threads using both java.lang.Thread and java.lang.Runnable

Creating Threads :
There are two ways

public class aThread extends Thread{
public void run() {
}
}

Every class that extends the Thread class should have a run() method that specifies whatever tasks are required when this thread is executed.
Now to start a new thread, you use the start() method, which is defined in the Thread class

Starting a Thread :

aThread t = new aThread().
t.start();

when the new class is instantiated and its start() method is called a new thread of control is created. The new thread then calls the run() method, which in this case is defined in aThread class.

public class aThread implements Runnable {
public void run() {

}
}

The following code would then create a thread and start it running:
aThread t = new aThread();
new Thread(t).start();

This method of creating threads of control is very useful if the class we want to run in a thread already extends some other class.

Remember : Creating a new Thread instance puts the thread into the "new thread" state. It is not "alive" until someone invokes the thread's start() method.



23) Recognize conditions that might prevent a thread from executing.

Every thread in the JVM can be in 4 states :

Conditions that might prevent a thread from executing :

24) Write code using synchronized wait notify and notifyAll to protect against concurrent access problems and to communicate between threads. Define the interaction between threads and object locks when executing synchronized wait notify or notifyAll.

Synchronization :

class Callme {
void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
} catch (Exception e){};
System.out.println("]");
}
}

class caller implements Runnable {
String msg;
Callme target;
public caller(Callme t, String s) {
target = t;
msg = s;
new Thread(this).start();
}
public void run() {
target.call(msg);
}
}

public class Synch {
public static void main(String args[]) {
Callme target = new Callme();
new caller(target, "Hello");
new caller(target, "Synchronized");
new caller(target, "World");
}
}

output :
[Hello[Synchronized[World]
]
]

class Callme {
synchronized void call(String msg) {
System.out.print("[" + msg);
try Thread.sleep(1000);
catch (Exception e);
System.out.println("]");
}
}

class caller implements Runnable {
String msg;
Callme target;
public caller(Callme t, String s) {
target = t;
msg = s;
new Thread(this).start();
}
public void run() {
target.call(msg);
}
}

class Synch1 {
public static void main(String args[]) {
Callme target = new Callme();
new caller(target, "Hello");
new caller(target, "Synchronized");
new caller(target, "World");
}
}

output :

[Hello]
[Synchronized]
[World]

synchronized (expression) statement;
public void run() {
synchronized(target) {
target.call(msg);
}
}

Inter-thread communication :

A non-synchronous Producer/Consumer problem :

class Q {
int n;
synchronized int get() {
System.out.println("Got: " + n);
return n;
}
synchronized void put(int n) {
this.n = n;
System.out.println("Put: " + n);
}
}

class Producer implements Runnable {
Q q;
Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}
public void run() {
int i = 0;
while(true) {
q.put(i++);
}
}
}

class Consumer implements Runnable {
Q q;
Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}
public void run() {
while(true) {
q.get();
}
}
}

class PC {
public static void main(String args[]) {
Q q = new Q();
new Producer(q);
new Consumer(q);
}
}

output :

Put: 1
Got: 1
Got: 1
Got: 1
Got: 1
Got: 1
Put: 2
Put: 3
Put: 4
Put: 5
Put: 6
Put: 7
Got: 7

class Q {
int n;
boolean valueSet = false;
int get() {
while (!valueSet)
;
System.out.println("Got: " + n);
valueSet = false;
return n;
}
void put(int n) {
while (valueSet)
;
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
}
}
Properly synchronized the queue via wait and notify :

class Q {
int n;
boolean valueSet = false;
synchronized int get() {
if (!valueSet) try {
wait();
} catch(InterruptedException e) {};
System.out.println("Got: " + n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n) {
if (valueSet) try {
wait();
} catch(InterruptedException e) {};
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
}
}

ouput :

Put: 1
Got: 1
Put: 2
Got: 2
Put: 3
Got: 3
Put: 4
Got: 4
Put: 5
Got: 5

Deadlock :

class A {
synchronized void foo(B b) {
String name = Thread.currentThread().getName();
System.out.println(name + " entered A.foo");
try {Thread.sleep(1000);} catch (Exception e) {};
System.out.println(name + " trying to call B.last()");
b.last();
}
synchronized void last() {
System.out.println("inside A.last");
}
}

class B {
synchronized void bar(A a) {
String name = Thread.currentThread().getName();
System.out.println(name + " entered B.bar");
try {Thread.sleep(1000);} catch (Exception e) {};
System.out.println(name + " trying to call A.last()");
a.last();
}
synchronized void last() {
System.out.println("inside B.last");
}
}

class Deadlock implements Runnable {
A a = new A();
B b = new B();
Deadlock() {
Thread.currentThread().setName("MainThread");
new Thread(this, "RacingThread").start();
a.foo(b); // get lock on a in this thread.
System.out.println("back in main thread");
}
public void run() {
b.bar(a); // get lock on b in other thread.
System.out.println("back in other thread");
}
public static void main(String args[]) {
new Deadlock();
}
}

ouput :

MainThread entered A.foo
RacingThread entered B.bar
MainThread trying to call B.last()
RacingThread trying to call A.last()
^C

Full Thread Dump:
"RacingThread" (... state:MONITOR_WAIT) prio=5
A.last(Deadlock.java:8)
B.bar(Deadlock.java:17)
Deadlock:run(Deadlock.java:32)
java.lang.Thread.run(Thread.java:289)
"MainThread" (... state:MONITOR_WAIT) prio=5
B.last(Deadlock.java:19)
A.foo(Deadlock.java:6)
Deadlock.(Deadlock.java:28)
Deadlock,main(Deadlock.java:36)
Monitor Cache Dump:
A@1393760/142E330 (key=0x1393760): "MainThread"
B@1393778/142E340 (key=0x1393778): "RacingThread"

Thread Summary :

The interface Runnable is defined as,
public abstract interface Runnable {
// Public Instance Methods
public abstract void run();
}

The class Thread in Java is defined as,
public class Thread extends Object implements Runnable {
// Public Constructors
public Thread();
public Thread(Runnable target)
public Thread(ThreadGroup group, Runnable target);
public Thread(String name);
public Thread(ThreadGroup group, String name);
public Thread(Runnable target, String name);
public Thread(ThreadGroup group, Runnable target, String name);
// Constants
public final static int MAX_PRIORITY;
public final static int MIN_PRIORITY;
public final static int NORM_PRIORITY;
// Class Methods
public static int activeCount();
public static Thread currentThread();
public static sleep(long millis) throws InterruptedException;
public static sleep(long millis, int nanos) throws InterruptedException;
public static void yield();
....
....
// Public Instance Methods
public void destroy();
public final int getPriority();
public final ThreadGroup getThreadGroup();
public void boolean isAlive();
public void run();
public void setPriority(int newPriority) throws IllegalArgumentException;
public final void stop();
public synchronized void stop(Throwable o);
public final void suspend();
.....
.....
}

Remember :




Copyright © 1999-2000, Jyothi Krishnan
All Rights Reserved.