1. Why cannot we synchronized public object to lock the memory for avoiding multi-thread access?
A:synchronized has nothing to do with locking memory, but controlling access to a block of code, which may access and change the memory/database/file contents, the integrity of which might be compromized by multi-thread simultaneous access or changes. Here, I intentionally missed how synchronized works, uses what kind of working mechanism. Read other part of the FAQ for that, please. public/private/protected access modifiers have no relationship with synchronized, even they share a word "access". They are for encapsulation, in other words, information sharing or hiding. Like your family, you may want certain information to be public, some to be known only by your relatives or close friends, some to be kept only to your family members. Some might be kept to yourself only, hoho, a secret. They are different concepts and serve different purposes.
2. I found this statement about thread in some tutorial on Internet, Is it true?
The main thread must be the last thread to finish execution. When the main thread stops, the program terminates.
A: Absolutely wrong!
The correct one:
JVM creates one user thread for running a program. This thread is called main thread. The main method of the class is called from the main thread. It dies when the main method ends. If other user threads have been spawned from the main thread, program keeps running even if main thread dies. Basically a program runs until all the user threads (non-daemon threads) are dead.This is actually most GUI (Swing) application works. The main thread creates a thread for the GUI frame work; then it finishes and becomes dead. The GUI will still running until the user closes it or something else kills it. Microsoft GUI application basically works the same way.
A simple sample code (even not GUI) here!
class T extends Thread {
boolean runflag = true;
public T(String name){
super(name);
}
public void run() {
int i = 0;
while (runflag) {
System.out.println(getName() + ": " + i++);
try
{
sleep((int)(700*Math.random()));
}
catch (InterruptedException e) {
}
}
System.out.println(getName() + " is stopping.");
}
void setRunFlagFalse() {
runflag = false;
}
public static void main(String args[]) {
T t1=new T("t1");
T t2=new T("t2");
T t3=new T("t3");
t1.setDaemon(true);
t1.start();
t2.start();
t3.start();
try
{
// let three threads run
Thread.sleep(600);
}
catch (InterruptedException e) {
}
// t2 will stop
t2.setRunFlagFalse();
System.out.println("t3 will not stop after main stop");
System.out.println("t1 will stop after all user threads stopped");
System.out.println("Use ^C to stop everything, when you had enough");
System.out.println("main thread is stopping.");
}
}
3. What is the basic concept of synchronized keyword, is it responsible to our data integrity?
A: The key concept of synchronized keyword is locking the code to prevent other thread to access the critical code when one thread is processing it. You need acquire the monitor/lock from an object to lock it, and one object only has one lock/monitor. That is why when one thread acquired the lock/monitor, other threads have to wait. Why you need to lock the code? Mostly you need to keep the integrity of your data, and which is very application specific. The locking mechanism actually knows nothing about it. It is NOT responsible for your data integrity at all. It is you, the application programmer, who is responsible for it. For example, if you want to keep the integrity of your client's bank account balance, you must synchronize all methods, which have access to and can change the balance. If you leave a loophole there, you probably will be fired by your boss, not Dr. Gosling or someone else who designed the locking mechanism. I just want to scare you... However, when you are synchronizing the code, which has access to the client's account balance, you probably still can change his/her email address or list of hobbies for advertisement purposes. Of course, if you are really serious on that stuff too, you might want to synchronize the code, which has access those data independently.Programmers need to practice some examples to really understand it. Some times, I still get confused. Concurrent programming is not an easy subject. It is not Java specific either. Race condition, dead lock, critical section, semaphore, monitor, thread scheduling, thread pooling, etc. etc...I'm still in the learning process... How about we learn together.
4. Why we should call Thread.start() to start a Thread? I called the run() method, no error or exception at all, why?
A: When you call Thread start() method, JVM will create a new Thread, then call run() method of the new Thread. The new Thread will run concurrently with the original calling Thread.If you directly call the run() method, the Thread will act as a normal Java object. No new Thread will be created. The code will run sequentially. Try the following code to see the difference, and get a feeling of concurrency.
// MyRun.java
public class MyRun implements Runnable {
public static void main(String argv[]) {
MyRun r = new MyRun();
Thread t = new Thread(r);
// t is still running after Main finished
t.start();
// No new thread created, Main finishes after run() returns
// t.run();
try {
// See concurrency if you call t.start()
// See sequential if you call t.run()
for (int i = 0; i < i =" 0;">
5.Thread t = null; t.yield(), is this legal? If it is, what is the effect of the statement?
A: Yes, but it is bad coding style. It is equivalent to Thread.yield(), which will cause the current thread to yield, and becomes ready state. The purpose of yield() is let other Thread has a chance to execute.Since yield() is a static method of Thread class, the only concern to compile is the type, that is why t.yield(); and Thread.yield(); are exact the same. However, it is confusing human beings. It is bad, but legal practice. It is good for you to really understand what is static method.
6. In some mocking exam, after the definition of Thread t = new Thread(); then both yield(); and t.yield(); are marked as alternative answers for causing the current running thread to pause. Is it generally correct?
A: No! It is generally incorrect. In some special situation, it will compile and work, however, it should still be considered as bad coding practice. The special case is: when yield(); is called inside a Thread class ( in a main, or other method ).You should use Thread.yield() instead to accomplish the task. For more discussion, read the question above.The following example shows you the general case, if you call yield(); it will not compile.
// ThreadTest.java
import java.io.*;
class MyThread extends Thread {
public void run(){
for (int i=0; i<5; i =" " t =" new">
7. What are the differences between notify() and notifyAll()? Do they release the object lock?
A: notify() does NOT relinquish the lock - it just lets the JVM know that it will be possible to wake up a Thread that called wait() when the current Thread exits the synchronized code. If you have more than one Thread wait() on an object, notify only wakes up one of them - you can't predict which one. notifyAll() tells the JVM that all Threads waiting will be eligible to run. The JVM will pick one - probably by looking at the priorities.
8. When Thread.sleep() is called inside a synchronized method or block, does the Thread release the object lock?
A: No, Thread definitely does not release the lock before it goes to sleep, if it is in a synchronized method or block. That is why we should use wait(), notify(), notifyAll() defined in Object in synchronized method or block. Do not sleep() there unless you want the program totally stop, please! Write some code, you will see it easyly. Or read JDK Doc here: http://java.sun.com/j2se/1.3/docs/api/java/lang/Thread.html#sleep(long)Here is a example, sleepInsteadOfWaitNotify() method causes t2 and t3 totally starved to death.
public class SleepTest implements Runnable{
public void run() {
while (true){
sleepInsteadOfWaitNotify();
}
}
synchronized void sleepInsteadOfWaitNotify() {
while (true) {
System.out.println(Thread.currentThread().getName() + "Go to sleep");
try{
Thread.sleep(400);
}
catch (Exception e){
System.out.println(e);
}
System.out.println(Thread.currentThread().getName() + "wake up");
}
}
public static void main (String[] args){
SleepTest t = new SleepTest();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
t1.setName("t1");
t2.setName("t2");
t3.setName("t3");
t1.setDaemon(true);
t2.setDaemon(true);
t3.setDaemon(true);
t1.start();
t2.start();
t3.start();
try {
// let daemon threads run
Thread.sleep(10000);
}
catch (InterruptedException e) {
}
System.out.println("If user thread is dead, all daemon threads die. ");
}
}
9. In what situation, an IllegalThreadStateException will be thrown?
A:1) If the thread was already started, you call start() again.
2) If this thread is active, you call setDaemon().
3) A deprecated method countStackFrames() also throws IllegalThreadStateException.
10. What will be affected by assign a name to a thread using setName("YourThreadName")?
A:
Quote from JDK documentation:
Every thread has a name for identification purposes. More than one thread may have the same name. If a name is not specified when a thread is created, a new name is generated for it.
Nothing changes by assigning your Thread a name. It only gives you the convenience of debug, since it has a name you know.
11. What is Thread.interrupt()supposed to do?
A:
interrupt is supposed to end the sleep or wait state of a Thread prematurely by causing an InterruptedException.
12.What is Daemon Threads?
A: A daemon thread opposites to a user thread. The Java Virtual Machine exits when the only threads running are all daemon threads. You threads are default to user thread unless you explicitly use method setDaemon(boolean on) to set it as daemon thread. Note: You cannot call setDaemon() after Thread has started, otherwise, an IllegalThreadStateException (RuntimeException) will be thrown. Make sure you read the JDK documentation of Thread and ThreadGroup. Javadoc is your best teacher to tell you almost anything and everything about Java Threads.See sample code at ThreadTest.java
13. Why Thread methods stop(), resume(), suspend() deprecated? How can we stop a thread without call stop()?
A: Why? Read here Why Are Thread.stop, Thread.suspend, Thread.resume and Runtime.runFinalizersOnExit Deprecated?
How? See the following example:
public class T extends Thread {
boolean runflag = true;
public T(String name){
super(name);
}
public void run() {
int i = 0;
while (runflag) {
System.out.println(getName() + ": " + i++);
try
{
sleep((int)(400*Math.random()));
}
catch (InterruptedException e) {
}
}
System.out.println(getName() + " is stopping.");
}
public void setRunFlagFalse() {
runflag = false;
}
public static void main(String args[]) {
T t1=new T("t1");
T t2=new T("t2");
T t3=new T("t3");
t1.start();
t2.start();
t3.start();
try
{
// let three threads run
Thread.sleep(1000);
}
catch (InterruptedException e) {
}
// stop them
t1.setRunFlagFalse();
t2.setRunFlagFalse();
t3.setRunFlagFalse();
}
}
15. Can I use Thread.interrupt() to kill a thread? Is it a good idea?
A: Yes, you can. As long as your handle the InterruptedException tricky enough in your Thread.run() method, you can use interrupt() to kill a thread.However, it is absolutely a bad idea to do this. Thread.interrupt() is a general purposed method to interrupt or stop whatever a thread is doing now, such as sleep, wait, or living. If you used a general purpose method to mean killing a thread, you create a side effect, and invite unaware programmers to make mistake since they only read Sun's Thread javadoc.Stop is general; stop life is special. General includes special, but general does not imply special. If it does, it is a side effect. If stop sign on the street does also imply stop life, that would be really bad!!!Never do this kind of stunt, please!
Please follow KISS rule in your code, Keep It Simple and Stupid, or Keep It Simple and Straight forward. Do your boss and current/future coworkers a favor please!
There is one exception, if you're the boss, you can do and ask your employees do whatever you want. If they do not follow your order, fire them!
If you want read more discussion about and opposite side of my opinion, read here!
16. What does the Thread.join() method do? Can you give an example?
A: The current running thread currT call another thread jobthread.join(), then wait until the jobthread to die.
For example, the current running thread, which spawns the jobthread to do something (do a long calculation, load several images, call somebody through satilite, etc. etc.). The jobthread has been coded to do its job and then terminate or die, in other words, the jobthread.run() method ends. The current thread will rely on jobthread's completion to continue its own work. The effect of calling jobthread.join() statement is that currT waits for jobthread to complete
public class JoinDemo {
public static void main(String[] args) {
Job job = new Job();
Thread jobthread = new Thread(job);
jobthread.start();
try {
// the current thread will wait until the job done
jobthread.join();
}
catch(Exception e){
}
System.out.println("Job done");
// do something else
}
}
class Job implements Runnable {
public void run(){
int i;
for (i=1; i<=200; i++ ){ if (i % 10 != 0) { System.out.print(i + ", "); } else { System.out.println(i); } } } }
17. Is class wide lock and instance lock independent of each other?
A: Yes. Why?
Every Java Object has one lock, and only one lock. If you want enter synchronized code, you have to acquire the lock first. When you enter the static synchronized code, you need to acquire the lock on the Class object.
When you enter the synchronized instance code, you need to acquire the lock on the instance object.
However, they are different objects with different locks, and independent of each other.When you call a synchronized static method you get a lock on NONE OF the instances of the class, except the Class object itself. Please pay attention to the difference between class and Class. Run the following code, it will tell you the whole story.
class MyObj {
String sName;
public MyObj(String name) {
sName = name;
}
// The Class Object of MyObj will be locked
// However, staticMethod() and instanceMethod() are independent of each other
public static synchronized void staticMethod(String sThreadName) {
try {
System.out.println(sThreadName + ": staticMethod start lock");
Thread.sleep((long)(Math.random() * 2000 + 1));
System.out.println(sThreadName + ": staticMethod finish lock");
}
catch (InterruptedException e) {
}
}
// The instance Object MyObj of will be locked
// However, staticMethod() and instanceMethod() are independent of each other
public synchronized void instanceMethod(String sThreadName){
try {
System.out.println(sThreadName + ": " + sName + ": instanceMethod start lock");
wait((long)(Math.random() * 2000 + 1));
System.out.println(sThreadName + ": " + sName + ": instanceMethod finish lock");
notifyAll();
}
catch (InterruptedException e) {
}
}
}
public class Test extends Thread{
String sTrdName;
// 2 objs for testing lock
static MyObj o1 = new MyObj("myobj1");
static MyObj o2 = new MyObj("myobj2");
public Test(String name){
super();
sTrdName = name;
}
public void run() {
while (true){
// Lock the Class object of MyObj
MyObj.staticMethod(sTrdName);
// Lock the instances object of MyObj
o1.instanceMethod(sTrdName);
o2.instanceMethod(sTrdName);
}
}
public static void main (String[] args){
Test t1 = new Test("t1");
Test t2 = new Test("t2");
t1.setDaemon(true);
t2.setDaemon(true);
t1.start();
t2.start();
try {
//let Daemon thread run
Thread.sleep(7000);
}
catch (InterruptedException e) {
}
System.out.println("If user thread is dead, all daemon threads die. ");
}
}
// Output of the program clearly tell you the story
/*
t1: staticMethod start lock
t1: staticMethod finish lock
t2: staticMethod start lock
t1: myobj1: instanceMethod start lock
t1: myobj1: instanceMethod finish lock
t1: myobj2: instanceMethod start lock
t2: staticMethod finish lock
t2: myobj1: instanceMethod start lock
t2: myobj1: instanceMethod finish lock
t2: myobj2: instanceMethod start lock
t1: myobj2: instanceMethod finish lock
t2: myobj2: instanceMethod finish lock
t2: staticMethod start lock
t2: staticMethod finish lock
t2: myobj1: instanceMethod start lock
t1: staticMethod start lock
t1: staticMethod finish lock
t1: myobj1: instanceMethod start lock
t2: myobj1: instanceMethod finish lock
t2: myobj2: instanceMethod start lock
t1: myobj1: instanceMethod finish lock
t1: myobj2: instanceMethod start lock
t2: myobj2: instanceMethod finish lock
t2: staticMethod start lock
t1: myobj2: instanceMethod finish lock
If user thread is dead, all daemon threads die.
*/
18. How to call wait(), notify(), notifyAll()
in synchronized static methods?
A: Direct calling those methods will not compile since those are instance methods inherited from Object. When you call wait()
, you are actually calling this.wait()
, this
does not exist in static methods.
How can we solve the problem? There are two ways to do it.
-
Call
wait(), notify(), notifyAll()
methods of yourClass
object, by usingMyClass.class.wait()
. synchronized static methods locks theClass
, you release lock of the same object. -
Instantiate a static Object
dummy
in your class, you can use synchronized block, which locksdummy
, in your static method. Then you can calldummy.wait(), dummy.notify(), ...
in those blocks.
This is better when you have more than one set of static methods, which needs locked independently, you can use more than one dummy objects for that purposes.
If your problem is something like that a Queue problem where add and remove are static methods working on static array. Lock the array object!!! See sample code snippet below.
static Object[] ary = new Object[50];
static void method1() {
System.out.println("do something not need to lock the ary...");
synchronized(ary){
System.out.println("do something on ary Object..");
try{
ary.wait();
}
catch(InterruptedException e) {
}
System.out.println("do something else on ary Object..");
}
System.out.println("do something else not need to lock the ary...");
}
19. What is race condition?
A:
Quote from The Java Tutorial:
Race conditions arise from multiple, asynchronously executing threads try to access a single object at the same time and getting the wrong result.
An excellent explanation of race condition here! Not Java specific!!!
http://www.kulua.org/Archives/kulua-l/199901/msg00025.html
20. What is Thread Deadlock? How to avoid it?
A: A deadlock occurs when one object is waiting for another to release a lock, and that object is also waiting. A circular dependency occurs, and then the waiting thread will wait forever, or deadlocked.The key to prevent deadlock: Do not hold a lock while waiting another resource that also requires locking.Read from Sun's tutorial:
http://java.sun.com/docs/books/tutorial/essential/threads/deadlock.html
Play with the famous Dining Philosopher Problem (not invented by Java!) Applet and learn the important concepts when you have fun.
21. What is Thread Starvation? How to avoid it?
A: For any reason, one or more threads never get a chance to run, or be blocked for a long time if not forever.Many reasons can cause Thread starvation:
-
Threads are deadlocked.
-
Thread is blocked by I/O, the I/O never become available again.
-
Other threads with higher priority run selfishly, never give other thread a chance to run.
-
Synchronized methods/blocks forget to release the lock/monitor. In Java, wrongfully using sleep/yield instead of wait/notify/notifyAll has a very good chance to cause deadlock/starvation.
-
Your Thread scheduling system does not working correctly.
-
...
How to avoid/correct them? Find out what causes your thread starvation, and correct them.
22. When a Thread die? Can a dead Thread be restarted?
A: No. a dead Thread cannot be restarted.
-
If you call its start() method after its death, IllegalThreadStateException will be thrown.
-
Even the Thread is dead, but you still can call its other method. Why? Simple, the Thread is just another Java Object. For example, if you call its run() method again, it will be just a sequential procedure call, no concurrent execution at all.
-
The exit() method of class Runtime has been called and the security manager has permitted the exit operation to take place.
-
Non daemon threads die, either by returning from call of the run() method or by throwing an exception that propagates beyond the run() method.
-
Daemon Threads die when all user Threads died.
23. When will a Thread I/O blocked?
A: When a thread executes a read() call on an InputStream, if no byte is available. The calling Thread blocks, in other words, stops executing until a byte is available or the Thread is interrupted.