This is some information on the Java 6 certification that I prepare. This information is not very well structured and it is most of the time an answer to the questions that come when I read the SCJP 6 book (Bates and Sierra). *** AS OF 5 OF MARCH 2010, I AM SCJP 6.0 ***

Saturday, March 27, 2010

36 - kick butt and have fun !

kick butt and have fun ! :-) 

 Until the next certification (Java 7 or 8) I continue the story on Java Easy !

35 - up to the next ! :-)

Monday, March 1, 2010

34 - What is printed ?

To relax you a little please make the following exercice and guess what is going to be printed ?


package ex1;

public class Main {

    String hello = "hello";

    {
        System.out.println(this.hello);
        System.out.println("block1");
    }

    public static void main(String[] args) {

        new Main().fool();

    }

    Main() {
        System.out.println("Main");
    }

    void fool() {
        System.out.println("fool");
    }

    {
        System.out.println("block2");
    }
}

==========
































run:
hello
block1
block2
Main
fool

Thursday, February 25, 2010

33 - AutoBoxing rules

It is my rules and please drop me an email if you read something incorrect !


Let's say you have several methods with the same name but different parameters(overloaded methods).


You pass a "primitive wrapper object" OR a primitive.


What is chosen ? and Why ?


Diagram :



A) a Short 

can become a Short or an Object (is an Object)


WILL NOT BECOME an Integer, a Long, a Float, a Double


Short is Short OR Object STOP


OR can become a short (a primitive)
look below

B) a short (primitive)

can become (what is short compatible) a short, a int, a long, a float, a double (I mean without a cast) STOP

OR

a Short (primitive wrapper)
Look now the way a Short is evaluated above.

I have to add a rule, var-arg parameters are ALWAYS - ALWAYS - ALWAYS :-) chosen LAST ! Look at example AB2 (AutoBoxing2).
I like the style of Kathy :-)


Examples

Please find the correct answers :


package autoboxing;

public class AB1 {

    static String method1(Short param) {
        return "Short";
    }
    static String method1(short param) {
        return "short";
    }

    public static void main(String[] args) {
        Short x = -32768;

        System.out.println(method1(x));
    }
}


package autoboxing;

public class AB2 {

    static String method1(Short... param) {
        return "Short...";
    }

    static String method1(Object param) {
        return "Object";
    }

    public static void main(String[] args) {
        Short x = -32768;

        System.out.println(method1(x));
    }
}

package autoboxing;

public class AB31 {

    static String method1(short param) {
        return "short";
    }

    static String method1(Object param) {
        return "Object";
    }

    public static void main(String[] args) {
        Short x = -32768;

        System.out.println(method1(x));
    }
}

package autoboxing;

public class AB32 {

    static String method1(short param) {
        return "short";
    }

    static String method1(double param) {
        return "double";
    }

    public static void main(String[] args) {
        Short x = -32768;

        System.out.println(method1(x));
    }
}

package autoboxing;

public class AB33 {

    static String method1(double param) {
        return "double";
    }

    static String method1(int param) {
        return "int";
    }

    public static void main(String[] args) {
        Short x = -32768;

        System.out.println(method1(x));
    }
}

package autoboxing;

public class AB4 {

    static String method1(short param) {
        return "short";
    }

    static String method1(Short param) {
        return "Short";
    }

    public static void main(String[] args) {
        short x = -32768;

        System.out.println(method1(x));
    }
}

package autoboxing;

public class AB5 {

    static String method1(double param) {
        return "double";
    }

    static String method1(Short param) {
        return "Short";
    }

    public static void main(String[] args) {
        short x = -32768;

        System.out.println(method1(x));
    }
}


package autoboxing;

public class AB6 {
    static String method1(Double param) {
        return "Double";
    }

    public static void main(String[] args) {
        short x = -32768;
        System.out.println(method1(x));
    }
}

package autoboxing;

public class AB7 {

    static String method1(Short param) {
        return "Short";
    }

    static String method1(Object param) {
        return "Object";
    }

    public static void main(String[] args) {
        short x = -32768;
        System.out.println(method1(x));
    }
}

package autoboxing;

public class AB8 {

    static String method1(Integer param) {
        return "Integer";
    }

    static String method1(Object param) {
        return "Object";
    }

    public static void main(String[] args) {
        short x = -32768;
        System.out.println(method1(x));
    }
}


























Answers :
AB1:Short,AB2:Object,AB31:Object,AB32:short,AB33:int,AB4:short,AB5:double,AB6:does not compile,AB7:Short,AB8:Object





Friday, February 19, 2010

32 - arrays - Java 1.6

I find the following very fascinating...

package basic;

public class Main {

    public static void main(String[] args) {

        Object d = new Long[4];
        Object[] e = (Object[]) d;
        System.out.println("e[0] : " + e[0]);

        Long[] f = (Long[]) d;
        System.out.println("\nf[0] : " + f[0] + "\n");


        Long[] g[] = {{1L, 2L}, {1L}};
        for (int i = 0; i < g.length; i++)
            for (int j = 0; j < g[i].length; j++)
                System.out.println(g[i][j]);
       
        System.out.println("");
        String[] s = new String[4];
        int i=0;
        for(String s1:s)
            System.out.println(i++ + ":" + s1);

        System.out.println("");
        int []t[] = new int[5][6];
        for(int k=0; k < t.length; k++) {
            int m = 0;
            for(int l:t[k]) {
                System.out.println(m++ + ":" + l);
            }
            System.out.println("");
        }
    }
}

run:
e[0] : null

f[0] : null

1
2
1

0:null
1:null
2:null
3:null

0:0
1:0
2:0
3:0
4:0
5:0

0:0
1:0
2:0
3:0
4:0
5:0

0:0
1:0
2:0
3:0
4:0
5:0

0:0
1:0
2:0
3:0
4:0
5:0

0:0
1:0
2:0
3:0
4:0
5:0

BUILD SUCCESSFUL (total time: 0 seconds)

31 - Covariant Return - Java 1.6

They use several time a covariant return in the master exams... Be careful...

I find the explanations here interesting

Example :

1) Java 1.1 and after (this will compile) - It is NOT a covariant return !!!


package covariantreturn;

public class A {
    A method() {
        return this;
    }
}

package covariantreturn;

public class B extends A {
    A method() {
        return this;
    }
}

package covariantreturn;

public class C extends B {
      A method() {
        return this;
    }
}

2a) Java 1.5 and after (will not compile in Java < 1.5 !!!) - Covariant Return !
You return a subtype of A in B
You return a subtype of B in C (can be B) 


package covariantreturn;

public class A {
    A method() {
        return this;
    }

}

package covariantreturn;

public class B extends A {
    B method() {
        return this;
    }
}

package covariantreturn;

public class C extends B {
      B method() {
        return this;
    }
}

2b) 

You return a subtype of A in B
You return a subtype of B in C (can be C) 

package covariantreturn;

public class A {
    A method() {
        return this;
    }

}

package covariantreturn;

public class B extends A {
    B method() {
        return this;
    }
}

package covariantreturn;

public class C extends B {
      C method() {
        return this;
    }
}

Sunday, February 7, 2010

0 - ERRATA - MASTER EXAM 1

Question 68
H java -cp /mp/jars/mp.jar player.MusicPlayer
INSTEAD OF
H java -cp /mp/jars/cp.jar player.MusicPlayer

IT IS TOTALLY UNACCEPTABLE !!! GUYS READ YOUR STUFF AND PRODUCE AN ERRATA !!!


But your book is so good that I forgive you Kathy and Bert :-)

Saturday, February 6, 2010

30 - Treeset - Java 1.6.0_18

package javaapplication15;

import java.util.Set;
import java.util.TreeSet;

public class Main {

    public static void main(String[] args) {

        Set treeSet = new TreeSet();

        treeSet.add("2"); treeSet.add("4"); treeSet.add("6"); treeSet.add("8");

        System.out.println("first : " + ((TreeSet)treeSet).first());
        System.out.println("floor(6) : " + ((TreeSet)treeSet).floor("6"));
        System.out.println("higher(6) : " + ((TreeSet)treeSet).higher("6"));
        System.out.println("last : " + ((TreeSet)treeSet).last());
    }

}



first : 2
floor(6) : 6
higher(6) : 8
last : 8

29 - Serialization - Transient - Constructor - Java 1.6.0_18

package serialization2;

import java.io.Serializable;

public class A  {
    int a1 = -1;
    int a2 = -2;
    int a3 = -3;

    A() {
        System.out.println("in A()");
    }
}

package serialization2;

import java.io.Serializable;

public class A1 extends A implements Serializable {
    int a;
    transient int b;

    A1(int a, int b) {
        this.a = a;
        this.b = b;
    }

    public String toString() {
        String aString = Integer.toString(super.a1)
                + " " + Integer.toString(super.a2)
                + " " + Integer.toString(super.a3)
                + " " + Integer.toString(a)
                + " " + Integer.toString(b);
        return aString;
    }
}


package serialization2;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import javax.imageio.stream.FileImageInputStream;

public class Main {
    public static void main(String[] args) throws Exception {
        A1 refA1 = new A1(-1,-2);
        System.out.println("refA1 : " + refA1);
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("A1.ser"));
        oos.writeObject(refA1);

        System.out.println("reading it back");

        refA1 =(A1)new ObjectInputStream(new FileInputStream("A1.ser")).readObject();
        System.out.println("refA1 : " + refA1);
        
    }
}

If A is not serializable 

run:
in A()
refA1 : -1 -2 -3 -1 -2
reading it back
in A()
refA1 : -1 -2 -3 -1 0

The constructor was called. b is transient and assigned 0.

If a is serializable

run:
in A()
refA1 : -1 -2 -3 -1 -2
reading it back
refA1 : -1 -2 -3 -1 0

The constructor was NOT called. b is still transient and still assigned 0.

Saturday, January 30, 2010

28 - Review - xxxValue() - parseXxx() - valueOf() - Java 1.6.0_17

package chap3review;

public class Main {

    public static void main(String[] args) {
      
        // NOT STATIC
        //xxxValue()

        Byte aByte = 125;
        byte b = aByte.byteValue();
        short s = aByte.shortValue();
        int i = aByte.intValue();
        long l = aByte.longValue();
        float f = aByte.floatValue();
        double d =  aByte.doubleValue();

        Integer aInteger = 6753;
        i = aInteger.intValue();
        l = aInteger.longValue();
        f = aInteger.floatValue();
        d = aInteger.doubleValue();

        Boolean aBoolean = true;
        boolean bo = aBoolean.booleanValue();

        // Static
        // parseXxx

        b = Byte.parseByte("127"); // Exception in thread "main" java.lang.NumberFormatException: Value out of range. Value:"256" Radix:10
        // 8 bits signed -128..127 !!!
        i = Integer.parseInt("123456");
        bo = Boolean.parseBoolean("TRUE");
      
        //static 
        // valueOf()

        Byte anotherByte = Byte.valueOf("-128");
        anotherByte = Byte.valueOf(b); // NO BYTE LITTERALS !!!

        Integer  anotherInteger = Integer.valueOf("123456");
        anotherInteger = Integer.valueOf(123456);
    }
}

Friday, January 29, 2010

27 - Review - type of an array - level basic - Java 1.6.0_17 - NB 6.8

What is the output ?

package pkg1;

public class Class10 {

    static Integer[] arrayofINT = { 1, 2, 3, 4 ,5};

    public static void main(String[] args) {

        if(arrayofINT instanceof Object) {
            System.out.println("arrayofINT is an Object !");
        }
        if(arrayofINT instanceof Integer[]) {
            System.out.println("arrayofINT is an Integer[] !");
        }
    }
}

run:
arrayofINT is an Object !
arrayofINT is an Integer[] !
BUILD SUCCESSFUL (total time: 0 seconds)

26 - Review - protected - level basic - Java 1.6.0_17 - NB 6.8

??? protected ??? All the buzz about this keyword...

Let's try to do it simple...

http://en.wikibooks.org/wiki/Java_Programming/Keywords/protected

protected means default + inheritance

  • If you are in a separate pkg, you have access to the protected members ONLY if you extend the class where the protected member is defined.
  •  In the class that extends the class where the protected member is defined you have access to the member using DIRECTLY the member name (only if you didn't you the same name in the class and in this case the member protected is hidden) and using the keyword 'super'. 
  • If the protected member is hidden then use super. If you want to access a method protected in a subclass user the member name (or again if it is hidden then use super).
  • Don't try to user super.super (or super.super.super). It is not implemented... If you want a member to be accessed from all the inheritance tree then make the name unique or (it is a possibility) make a kind of proxy member that will have to call super from the parent class (I don't like this).
example :






/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pkg3.pkg31;

/**
 *
 * @author Rudy
 */
public class Class1 {

    private int a;
    private int b;

    protected int c = -1;

    protected int d = -888;

    protected Class1(int a, int b) {
        System.out.println("Class1-protected Class1(int a, int b)");
        this.a = a;
        this.b = b;
    }

    protected int calculation() {
        System.out.println("Class1-protected int calculation()");
        return a + b;
    }


    protected void simplyToAnnoyYou() {
        System.out.println("simplyToAnnoyYou");
    }




    public static void main(String[] args) {
        System.out.println("main from pkg31.Class1\n");

        System.out.println(new Class1(1, 2).calculation());
    }
}

run:
main from pkg31.Class1

Class1-protected Class1(int a, int b)
Class1-protected int calculation()
3
BUILD SUCCESSFUL (total time: 0 seconds)

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pkg3.pkg32;

/**
 *
 * @author Rudy
 */
public class Class2 extends pkg3.pkg31.Class1 {

    Class2(int a, int b) {
        super(a, b);
        System.out.println("Class2(int a, int b)");
        super.c = -2;
    }

    @Override
    protected int calculation() {
        System.out.println("Class2-protected int calculation()");
        return super.calculation();
    }

    protected int calculation1() {
        System.out.println("Class2-protected int calculation1()");
        int a = super.calculation() + super.c + c;
        return a;
    }

    public static void main(String[] args) {
        System.out.println("main from pkg32.Class2\n");

        Class2 class2 = new Class2(1, 3);

        System.out.println("class2.calculation :  " + class2.calculation());

        System.out.println("c from class1 (protected) in class 2: " + class2.c);

        System.out.println("calculation1 : " + class2.calculation1());
    }
}

run:
main from pkg32.Class2

Class1-protected Class1(int a, int b)
Class2(int a, int b)
Class2-protected int calculation()
Class1-protected int calculation()
class2.calculation :  4
c from class1 (protected) in class 2: -2
Class2-protected int calculation1()
Class1-protected int calculation()
calculation1 : 0
BUILD SUCCESSFUL (total time: 0 seconds)






/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pkg3.pkg32;

/**
 *
 * @author Rudy
 */
public class Class3 extends Class2 {

    int d = -999;

    Class3(int a, int b) {
        super(a, b);
        System.out.println("Class3(int a, int b)");
        super.c = -4;
    }

    @Override
    protected int calculation() {
        System.out.println("Class3.calculation()");
        return super.calculation();
    }

    @Override
    protected int calculation1() {
        System.out.println("Class3.calculation1()");
        int a = super.calculation() + super.c + c;
        return a;
    }

    int getD() {
        return super.d;
    }

    public static void main(String[] args) {
        System.out.println("main from pkg32.Class2\n");

        Class3 class3 = new Class3(1, 3);

        System.out.println("class3.calculation :  " + class3.calculation());

        System.out.println("c from class1 (protected) in class 2: " + class3.c);

        System.out.println("calculation1 : " + class3.calculation1());

        System.out.println("d : " + class3.d);
        
        System.out.println("d from class1 and not defined in class 2 but hidden in class3 : " + class3.getD());

        class3.simplyToAnnoyYou();
    }
}

run:
main from pkg32.Class2

Class1-protected Class1(int a, int b)
Class2(int a, int b)
Class3(int a, int b)
Class3.calculation()
Class2-protected int calculation()
Class1-protected int calculation()
class3.calculation :  4
c from class1 (protected) in class 2: -4
Class3.calculation1()
Class2-protected int calculation()
Class1-protected int calculation()
calculation1 : -4
d : -999
d from class1 and not defined in class 2 but hidden in class3 : -888
simplyToAnnoyYou
BUILD SUCCESSFUL (total time: 0 seconds)

Can you explain all the output ?
:-)



Thursday, January 28, 2010

25 - Review - private - level basic - Java 1.6.0_17 - NB 6.8

I wanted to make you aware (if you are not) of the following...

If you make your constructor "private" you can't invoke the constructor from another class... But you can still invoke it from the SAME class. In Netbeans we are used that Netbeans will generate automatically a Main class and a pvsm (public static void main[] args) method in the main class. In this case if you try to instantiate a class using a private constructor you cant... You have to give another ways (have a look to singletons). But if you put a pvsm in the class were the private constructor is defined, no problem you can instantiate the class.

package pkg3.pkg31;



class Class1 {


    protected int a;
    protected int b;


    private Class1(int a, int b) {
        this.a = a;
        this.b = b;
    }


    protected int calculation() {
        return a + b;
    }


    public static void main(String[] args) {
        System.out.println(new Class1(1, 2).calculation());
    }
}

run:
3
BUILD SUCCESSFUL (total time: 0 seconds)

Tuesday, January 26, 2010

24 - Thread : notify/notifyall- level basic - Java 1.6.0_17 - NB 6.8

(
after all the Master Exam questions, they ask you several times to choose notify or notifyAll ...
most of the time if you answer (please read the question carefully) notifyAll, it is the wrong answer...
why ? it is because there is a producer and several consumers... after the producer produced something the producer will notify the consumers... the way they wrote the example, they do a wait but as soon as the thread is notified they do not check that something was produced (in the consumer thread)
if the producer do notifyAll, then (and it is not new) only 1 thread continues in the synchronized block...
this thread will consume what was produced and exit the synch block and it is fine...
but if notifyAll was used by the producer, then the second, third,... thread (one of those) are now notified but... nothing was produced and a thread will...consume (without checking that something was produced) and...that can cause a IndexOutOfBoundsException to be thrown if the thread calls (by ex) refArrayList.remove(0) without checking that the ArrayList is empty... If you answer notify, then only one thread will be notified and then consume... Then the producer after a while (sometimes they put a sleep) will produce and then call notify...
imho you serialize the way you produce and consume


you produce
then notify1 amongst all the threads
...

or
you produce
then notifyAll

all the threads will be able to continue before the producer produced (one by one in the synch blcok)
and that can cause a problem
(I repeat you have to find a way that the producer made something new)

*** Hope this help ***

)



3 classes. A Main that will start the threads. A producer (calling notify/notifyall) and  consumers.

The Producer

package threadnotifyall;

public class Calculator extends Thread {

    int total;

    public void run() {
        try {
            System.out.println("Calculator...");
            Thread.currentThread().sleep(1000);
            synchronized (this) {
                for (int i = 0; i < 100; i++) {
                    total += i;
                }
                Thread.currentThread().sleep(5000);
                notifyAll(); // OR
                //notify();
            }
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        }
    }
}

The Consumer

package threadnotifyall;

public class Reader extends Thread {
    Calculator c; // reference to the producer

    public Reader(Calculator c) {
        this.c = c;
    }

    public void run() { // it is a thread 
        synchronized(c) { // lock the producer (try to lock)
            try {
                System.out.println(Thread.currentThread().getName() + " waiting for calculation...");
                c.wait(); // if the producer is locked but did not notify (us) wait to be notified (1 and only 1 thread !) or wait forever (see my remarks later)
            } catch(InterruptedException ie) {
                ie.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()  + " Total is :" + c.total); // show the thread that was notified
        }
    }
}

The bandmaster

package threadnotifyall;

public class Main {

    public static void main(String[] args) {
      
        Calculator calculator = new Calculator(); // the producer

        new Reader(calculator).start(); // 3 consumers threads (we pass the producer they have to wait for)
        new Reader(calculator).start();
        new Reader(calculator).start();
        calculator.start(); // the 3 consumers were started (all waiting and the producer shows up)
        System.out.println("end of main"); // end of the THREAD main (because main is a THREAD)
    }
}

With notify

IT IS AN ASSUMPTION BECAUSE THE WAY THE JAVA SCHEDULER WILL CHOOSE THE THREAD DEPENDS ON A FEW FACTORS (WE CAN INFLUENCE)

run:
Thread-1 waiting for calculation...
Thread-2 waiting for calculation...
Thread-3 waiting for calculation...
end of main
Calculator...
Thread-1 Total is :4950
Thread-3 Total is :4950
Thread-2 Total is :4950
BUILD SUCCESSFUL (total time: 5 seconds)

run:
Thread-1 waiting for calculation...
Thread-2 waiting for calculation...
end of main
Thread-3 waiting for calculation...
Calculator...
Thread-1 Total is :4950
Thread-3 Total is :4950
Thread-2 Total is :4950
BUILD SUCCESSFUL (total time: 5 seconds)

I did several executions and can report that if we use notify, it is always the first thread that was started that will be choosen (notified that the producer has something to deliver). In the output as it is Thread-1 that was the first to be started (and waiting), Thread-1 is the first to be notified... You can see that the main thread terminated BEFORE the 3 threads were terminated. But Java is polite :-) and will wait that the 3 consumers threads will terminate.

With notifyall

run:
Thread-1 waiting for calculation...
Thread-2 waiting for calculation...
end of main
Thread-3 waiting for calculation...
Calculator...
Thread-3 Total is :4950
Thread-2 Total is :4950
Thread-1 Total is :4950
BUILD SUCCESSFUL (total time: 5 seconds)

run:
Thread-1 waiting for calculation...
Thread-3 waiting for calculation...
Thread-2 waiting for calculation...
end of main
Calculator...
Thread-2 Total is :4950
Thread-3 Total is :4950
Thread-1 Total is :4950
BUILD SUCCESSFUL (total time: 5 seconds)

run:
Thread-1 waiting for calculation...
Thread-3 waiting for calculation...
Thread-2 waiting for calculation...
end of main
Calculator...
Thread-2 Total is :4950
Thread-3 Total is :4950
Thread-1 Total is :4950
BUILD SUCCESSFUL (total time: 5 seconds)

As you can see using notifyall, it is the last thread that was started that was notified this time.

Following my experimentation with the kind of JVM that I use
  • If notify is used, then it is the thread that was the FIRST to be waiting that will be notified. Then the second,... Then the third... until all the threads waiting to be notified.
  • If notifyall is used, then it is the thread that was the LAST to be waiting that will be notified, then the previous, etc.
  • The Java scheduler will choose a thread to be notified (there is a list of threads awaiting) and the one that is awaken continues JUST AFTER the wait !!! But the awaken thread does not have to execute "synchronized" to get the lock. The Java scheduler guaranty the thread to receive the lock if the thread is chosen. ALL the other threads ARE WAITING to be notified (IMHO there are NOT in the runnable queue; the threads are in a special queue). They will all be notified ONE BY ONE. The way there are chosen depends on notify / notifyall. But the mechanism to awake the threads is the same. One by one !!! But look in the beg of this post, if nothing was produced and the thread that is awaken does not check that something is produced (with notifyAll) you can cause a IndexOutOfBoundsException to be thrown !!!
  • If you inverse the consumers and the producers meaning you start the producer first and later the consumer and let's say you also put a sleep just after the producer finishes. The consumers will ALL wait to be notified but will never be notified because the producer finished before any consumers were started. You see that the main thread is finished, but all the others keep waiting FOREVER !!! Thus the sequence of events is important and it is written  in the Sierra/Bates book that you have to wait for something that will happen (by example there is something to be read  from a queue and it is your application queue) but NOT unconditionaly !!!


Monday, January 25, 2010

23 - Thread : deadlock - level basic - Java 1.6.0_17 - NB 6.8

A deadlock is rather easy to produce having 2 actors (2 threads) accessing 2 resources at the same time but in different order !

T1-------------T2
res A----------res B
res B----------res A

If T1 put a lock on res A, T2 put a lock on res B, then T1 tries to lock res B (waiting the lock on res B to be released) an then T2 tries to lock res A (waiting the lock put by T1 to be released). The 2 threads do not speak to each others and will wait...indefinitely... The JVM seems not able to deal with such a problem...
You have to deal with it !!!


package threaddeadlock;

public class Main implements Runnable {

    ClassA refA = new ClassA();
    ClassB refB = new ClassB();

    void operation1() throws Exception {
        synchronized (refA) {
            refA.method1();
            synchronized (refB) {
                refB.method2();
            }
        }
    }

    void operation2() throws Exception {
        synchronized (refB) {
            refB.method2();
            synchronized (refA) {
                refA.method1();
            }
        }
    }

    public void run() {
        try {
            if (Thread.currentThread().getName().equals("t1")) {
                operation1();
            } else if (Thread.currentThread().getName().equals("t2")) {
                operation2();
            } else { // should be an assertion !!!
                System.err.println("thread name must be t1 or t2 !!!");
                System.exit(1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Main main = new Main();
        Thread t1 = new Thread(main);
        t1.setName("t1");
        Thread t2 = new Thread(main);
        t2.setName("t2");
        t1.start();
        t2.start();
    }
}

wait forever in front of your screen... :-)


run:
t1 method1
t2 method2
BUILD STOPPED (total time: 13 minutes 30 seconds)



package threaddeadlock;

public class ClassA {

     void method1() {
        System.out.println(Thread.currentThread().getName() + " method1");
    }

}

package threaddeadlock;

public class ClassB {

     void method2() {
        System.out.println(Thread.currentThread().getName() + " method2");
    }
}



22 - Thread : same or different object ? - level basic - Java 1.6.0_17 - NB 6.8

Look at the 2 versions of main
1 will create a new object of type ClassA for every thread
the second will not and look at the difference !


package threadsleep;

public class Main {

    public static void main(String[] args) {
        // 1st version new object ClassA of every thread
        //ClassA ca = new ClassA();
        //Thread thread;
        for(int i=0; i < 10; i++) {
            //thread = new Thread(ca);
            //thread.start();
            new Thread(new ClassA()).start();
        }
    }
}

run:
Thread-0
a : Thread-0 sleeping 5 seconds...
Thread-1
a : Thread-1 sleeping 5 seconds...
Thread-3
a : Thread-3 sleeping 5 seconds...
Thread-5
a : Thread-5 sleeping 5 seconds...
Thread-7
a : Thread-7 sleeping 5 seconds...
Thread-6
a : Thread-6 sleeping 5 seconds...
Thread-2
a : Thread-2 sleeping 5 seconds...
Thread-4
a : Thread-4 sleeping 5 seconds...
Thread-8
a : Thread-8 sleeping 5 seconds...
Thread-9
a : Thread-9 sleeping 5 seconds...
a : Thread-0-Thread-0 after sleeping 5 seconds...
a : Thread-1-Thread-1 after sleeping 5 seconds...
a : Thread-5-Thread-5 after sleeping 5 seconds...
a : Thread-3-Thread-3 after sleeping 5 seconds...
a : Thread-7-Thread-7 after sleeping 5 seconds...
a : Thread-6-Thread-6 after sleeping 5 seconds...
a : Thread-2-Thread-2 after sleeping 5 seconds...
a : Thread-4-Thread-4 after sleeping 5 seconds...
a : Thread-9-Thread-9 after sleeping 5 seconds...
a : Thread-8-Thread-8 after sleeping 5 seconds...
BUILD SUCCESSFUL (total time: 10 seconds)

The instance variable "a" was not modified because for every thread there is a different "a" !

public class Main {

    public static void main(String[] args) {
        // 2nd version the thread will share the same object
        ClassA ca = new ClassA();
        Thread thread;
        for(int i=0; i < 10; i++) {
            thread = new Thread(ca);
            thread.start();
            //new Thread(new ClassA()).start();
        }
    }
}

run:
Thread-0
a : Thread-0 sleeping 5 seconds...
Thread-1
a : Thread-1 sleeping 5 seconds...
Thread-2
a : Thread-2 sleeping 5 seconds...
Thread-3
a : Thread-3 sleeping 5 seconds...
Thread-5
a : Thread-5 sleeping 5 seconds...
Thread-7
a : Thread-7 sleeping 5 seconds...
Thread-9
a : Thread-9 sleeping 5 seconds...
Thread-4
a : Thread-4 sleeping 5 seconds...
Thread-6
a : Thread-6 sleeping 5 seconds...
Thread-8
a : Thread-8 sleeping 5 seconds...
a : Thread-8-Thread-0 after sleeping 5 seconds...
a : Thread-8-Thread-1 after sleeping 5 seconds...
a : Thread-8-Thread-2 after sleeping 5 seconds...
a : Thread-8-Thread-5 after sleeping 5 seconds...
a : Thread-8-Thread-3 after sleeping 5 seconds...
a : Thread-8-Thread-7 after sleeping 5 seconds...
a : Thread-8-Thread-9 after sleeping 5 seconds...
a : Thread-8-Thread-4 after sleeping 5 seconds...
a : Thread-8-Thread-6 after sleeping 5 seconds...
a : Thread-8-Thread-8 after sleeping 5 seconds...
BUILD SUCCESSFUL (total time: 11 seconds)

The thread "8" had a big influence on all the others threads because the thread "8" modified the instance variable "a" ! In fact it is because this poor thread "8" was the last to be started and as he is the last, he modified the same "a" instance variable for all the threads !!!

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package threadsleep;

public class ClassA implements Runnable {

    String a;

    public void run() {
        Thread currenthread = Thread.currentThread();
        a = currenthread.getName();
        System.out.println(a);
        try {
            System.out.println("a : " + a + " sleeping 5 seconds...");
            currenthread.sleep(10000);
            System.out.println("a : " + a + "-" + currenthread.getName()+ " after sleeping 5 seconds...");
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        }
    }
}

You can share the same objects. You will avoid to waste memory... But if your threads modify the data... You have to find a way keep the operations/data modifications consistent... In other words all the operations you do that can corrupt the data have to be atomic to avoid the corruption...


- Rudy -


21 - example of Thread.join - level basic - Java 1.6.0_17 - NB 6.8

3 classes
Main
ClassA
and ClassB
Main will start 2 threads one of ClassA and one of ClassB.
The threads do a loop and wait some time after each iteration.
After 3 seconds Main will send a message to ClassA (thread A) to join the Thread B.
(ClassA will check an instance variable and if this instance variable is initialized, then it is the thread to join)


package threadjoin;

public class Main {

    public static void main(String[] args) {

        ClassA a = new ClassA();
        ClassB b = new ClassB();

        Thread ta = new Thread(a);
        Thread tb = new Thread(b);

        ta.start();
        tb.start();

        System.out.println("sleeping 3 seconds ! then will force Thread A to join Thread B !");
        Thread main = Thread.currentThread();
        try {
            main.sleep(3000);
            a.threadToJoin = tb;
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        }


        System.out.println("after 3 seconds and thread A should join thread B !");
    }
}

package threadjoin;

/**
 *
 * @author Rudy
 */
public class ClassA implements Runnable {

    Thread threadToJoin;
    final static int counter = 100;
    final static int timeToWait = 100000000;

    public void run() {
        for (int c = 0; c < counter; c++) {
            System.out.println("A --- Loop #" + c);
            for (int t = 0; t < timeToWait; t++);
            if (threadToJoin != null) {
                try {
                    System.out.println("Thread A joining Thread B !!!");
                    threadToJoin.join();
                    // deactivation of the test !
                    threadToJoin = null;
                } catch (InterruptedException ie) {
                    ie.printStackTrace();
                }
            }
        }

    }
}

package threadjoin;

/**
 *
 * @author Rudy
 */
public class ClassB implements Runnable {

    final static int counter = 100;
    final static int timeToWait = 100000000;

    public void run() {
        for (int c = 0; c < counter; c++) {
            System.out.println("B --- Loop #" + c);
            for (int t = 0; t < timeToWait; t++);
        }

    }
}

run:
sleeping 3 seconds ! then will force Thread A to join Thread B !
A --- Loop #0
B --- Loop #0
A --- Loop #1
B --- Loop #1
A --- Loop #2
B --- Loop #2
A --- Loop #3
B --- Loop #3
A --- Loop #4
B --- Loop #4
A --- Loop #5
B --- Loop #5
A --- Loop #6
B --- Loop #6
B --- Loop #7
A --- Loop #7
B --- Loop #8
A --- Loop #8
B --- Loop #9
A --- Loop #9
B --- Loop #10
A --- Loop #10
B --- Loop #11
A --- Loop #11
B --- Loop #12
A --- Loop #12
B --- Loop #13
A --- Loop #13
B --- Loop #14
A --- Loop #14
B --- Loop #15
A --- Loop #15
B --- Loop #16
A --- Loop #16
B --- Loop #17
A --- Loop #17
B --- Loop #18
A --- Loop #18
B --- Loop #19
A --- Loop #19
B --- Loop #20
A --- Loop #20
B --- Loop #21
A --- Loop #21
B --- Loop #22
B --- Loop #23
A --- Loop #22
B --- Loop #24
A --- Loop #23
B --- Loop #25
A --- Loop #24
B --- Loop #26
A --- Loop #25
B --- Loop #27
A --- Loop #26
B --- Loop #28
A --- Loop #27
B --- Loop #29
A --- Loop #28
B --- Loop #30
A --- Loop #29
B --- Loop #31
A --- Loop #30
B --- Loop #32
A --- Loop #31
B --- Loop #33
A --- Loop #32
B --- Loop #34
A --- Loop #33
B --- Loop #35
A --- Loop #34
B --- Loop #36
A --- Loop #35
B --- Loop #37
A --- Loop #36
B --- Loop #38
A --- Loop #37
B --- Loop #39
A --- Loop #38
B --- Loop #40
A --- Loop #39
B --- Loop #41
A --- Loop #40
B --- Loop #42
A --- Loop #41
B --- Loop #43
A --- Loop #42
B --- Loop #44
A --- Loop #43
B --- Loop #45
A --- Loop #44
B --- Loop #46
A --- Loop #45
B --- Loop #47
A --- Loop #46
B --- Loop #48
A --- Loop #47
B --- Loop #49
A --- Loop #48
B --- Loop #50
A --- Loop #49
B --- Loop #51
A --- Loop #50
B --- Loop #52
A --- Loop #51
B --- Loop #53
after 3 seconds and thread A should join thread B !
Thread A joining Thread B !!!
B --- Loop #54
B --- Loop #55
B --- Loop #56
B --- Loop #57
B --- Loop #58
B --- Loop #59
B --- Loop #60
B --- Loop #61
B --- Loop #62
B --- Loop #63
B --- Loop #64
B --- Loop #65
B --- Loop #66
B --- Loop #67
B --- Loop #68
B --- Loop #69
B --- Loop #70
B --- Loop #71
B --- Loop #72
B --- Loop #73
B --- Loop #74
B --- Loop #75
B --- Loop #76
B --- Loop #77
B --- Loop #78
B --- Loop #79
B --- Loop #80
B --- Loop #81
B --- Loop #82
B --- Loop #83
B --- Loop #84
B --- Loop #85
B --- Loop #86
B --- Loop #87
B --- Loop #88
B --- Loop #89
B --- Loop #90
B --- Loop #91
B --- Loop #92
B --- Loop #93
B --- Loop #94
B --- Loop #95
B --- Loop #96
B --- Loop #97
B --- Loop #98
B --- Loop #99
A --- Loop #52
A --- Loop #53
A --- Loop #54
A --- Loop #55
A --- Loop #56
A --- Loop #57
A --- Loop #58
A --- Loop #59
A --- Loop #60
A --- Loop #61
A --- Loop #62
A --- Loop #63
A --- Loop #64
A --- Loop #65
A --- Loop #66
A --- Loop #67
A --- Loop #68
A --- Loop #69
A --- Loop #70
A --- Loop #71
A --- Loop #72
A --- Loop #73
A --- Loop #74
A --- Loop #75
A --- Loop #76
A --- Loop #77
A --- Loop #78
A --- Loop #79
A --- Loop #80
A --- Loop #81
A --- Loop #82
A --- Loop #83
A --- Loop #84
A --- Loop #85
A --- Loop #86
A --- Loop #87
A --- Loop #88
A --- Loop #89
A --- Loop #90
A --- Loop #91
A --- Loop #92
A --- Loop #93
A --- Loop #94
A --- Loop #95
A --- Loop #96
A --- Loop #97
A --- Loop #98
A --- Loop #99
BUILD SUCCESSFUL (total time: 9 seconds)

As you can see the Java scheduler will make the thread A and B execute at the same time.
We see

A --- Loop #0
B --- Loop #0
A --- Loop #1
B --- Loop #1
A --- Loop #2
B --- Loop #2
A --- Loop #3
B --- Loop #3
A --- Loop #4
B --- Loop #4
A --- Loop #5
B --- Loop #5
A --- Loop #6
...

Then after 3 seconds A joined B and thus A wait until the end of B.
We see

B --- Loop #54
B --- Loop #55
B --- Loop #56
B --- Loop #57
B --- Loop #58
B --- Loop #59
B --- Loop #60
B --- Loop #61
B --- Loop #62
B --- Loop #63
B --- Loop #64
B --- Loop #65
B --- Loop #66
B --- Loop #67
B --- Loop #68
B --- Loop #69
B --- Loop #70
B --- Loop #71
B --- Loop #72
B --- Loop #73
...
B --- Loop #94
B --- Loop #95
B --- Loop #96
B --- Loop #97
B --- Loop #98
B --- Loop #99

Look A is back !!!

A --- Loop #52
A --- Loop #53
A --- Loop #54
A --- Loop #55
A --- Loop #56
A --- Loop #57
A --- Loop #58
A --- Loop #59
A --- Loop #60
A --- Loop #61
A --- Loop #62
A --- Loop #63
A --- Loop #64
A --- Loop #65
A --- Loop #66
A --- Loop #67
A --- Loop #68
A --- Loop #69
A --- Loop #70
A --- Loop #71
A --- Loop #72
A --- Loop #73
A --- Loop #74
A --- Loop #75
A --- Loop #76
...
A --- Loop #86
A --- Loop #87
A --- Loop #88
A --- Loop #89
A --- Loop #90
A --- Loop #91
A --- Loop #92
A --- Loop #93
A --- Loop #94
A --- Loop #95
A --- Loop #96
A --- Loop #97
A --- Loop #98
A --- Loop #99


- Rudy -


Friday, January 22, 2010

20 - non public class and public method - level very basic - Java 1.6.0_17 - NB 6.8

OK it's for newbies...

But is it clear in your mind ?
If the class is not public even if the method is public you can't use the method !

package javaapplication10;

class Main { // where is public ???

    public void a() { // it is public !!!
        System.out.println("a");
    }

    public static void main(String[] args) {
        new Main().a(); // here you can
    }
}

package newpackage;

import javaapplication10.Main; // DOES NOT COMPILE !

public class Test {

    public static void main(String[] args) {
        new Main().a(); // DOES NOT COMPILE !

    }
}

Saturday, January 16, 2010

19 - hashCode - level basic - Java 1.6.0_17 - NB 6.8

TO BE REPHRASED !!!

To summarize

It is not enough to override "equals" and then try to retrieve keys in a map... If the 2 objects are equal, then the hash codes have to be the same. I suppose they play a max on this one...

More on this topic

You put an object in a map(the key). Then you change the object. And you base the hash code on the length of the String... The key changed but the method "get" will look in the bucket corresponding to the new hash code and will not find the value...

pseudo code

key1, value1
length("key1") => bucket 4
then you change key1 in "key11"
the object is still in bucket 4 but the hash code will reference the bucket5 !!! because lenght("key11") is... 5 !!!
It is not a good idea to change the key... I pref remove and then add...

To understand the statement on p 554, I propose to study the following example :

1) equals is overridden and hashCode is not.
2) equals is overridden and and hashCode is overridden and returns always 0.
3) equals is overridden and hashCode is overridden and returns the length of the string.

package mapandkeys;


public class Dog {

    String name;

    public Dog(String n) {
        name = n;
    }

    public boolean equals(Object o) {
        System.out.println("accessing method equals");
        if((o instanceof Dog) && (((Dog)o).name == name)) {
           return true;
        }
        return false;
    }


hasCode NOT OVERRIDDEN

OR

//    public int hashCode() {
//        System.out.println("accessing method hashcode");
//        return 0;
//
//    }

OR

//    public int hashCode() {
//        System.out.println("accessing method hashcode");
//        return name.length();
//
//    }


     public String toString() {
         return name;
     }
}


package mapandkeys;

public class Cat {
}

package mapandkeys;

import java.util.HashMap;
import java.util.Map;

public class Main {

    public static void main(String[] args) {
        Map m = new HashMap();
        m.put("k1", "k1");
        m.put("k2", "k2");
        System.out.println("1 size:" + m.size());

        String aString = (String) m.get("k1");

The 3 will return "k1"
default : it is the same "k1" from the string pool and hashCode will return the same id
0 : all objects will return the same bucket (bucket 0)
lenght : have the same length (bucket 2)

        System.out.println("2 aString : " + aString);

        m.put(new Dog("dog1"), "dog1");
        m.put(new Dog("dog2"), "dog2");
        System.out.println("3 size:" + m.size());
        aString = (String) m.get(new Dog("dog1"));
        System.out.println("4 aString : " + aString);
        aString = (String) m.get(new Dog("dog2"));
        System.out.println("5 aString : " + aString);

default : You do a new 2 times and the default hashCode will return 2 diffent hash ! You will not be able to retrieve the values !!!
0 and length will return the hash same thus we can retrieve the keys.

        Cat aCat = new Cat();
        System.out.println("hash of aCat :" + aCat.hashCode());
        m.put(aCat, "cat1");
        System.out.println("6 size:" + m.size());
        aString = (String) m.get(aCat);
        System.out.println("7 aString : " + aString);

Nothing was overridden in the Cat class and you do a "get" on the same cat (same object and same hash code) so the "cat1" is returned.

        Dog d1Key = new Dog("cloverkey");
        Dog d1Value = new Dog("clovervalue");
        m.put(d1Key, d1Value);
        System.out.println("8 size:" + m.size());
        System.out.println("9 d1Value : " + m.get(d1Key));

It is the same object and can be found in the 3 cases.

        d1Value.name = "clovervalue1";
        System.out.println("10 size:" + m.size());
        System.out.println("11 d1Value : " + m.get(d1Key));

The value was changed but not the key. The 3 will return the same (new) value.

        d1Key.name = "1";

The key is changed !!! It was "cloverkey" and now it is "1" !

        System.out.println("12 d1Value() : " + m.get(d1Key));

This time we change the key ! The hash code will make a difference...
def and 0, both point to the same bucket
length("clovervalue") and length("1") are different... Java will try to find the key in the wrong bucket !

        Dog d2 = new Dog("1");
        System.out.println("13 d1Value() : " + m.get(d2));

default : it is a different object because we used the keyword new !
0 : OK They all use the bucket 0 and it is not performant !
lenght : NOK because the length("clovervalue") = 11  and length("1") = 1 the value is in bucket 11 and we try to find the value in bucket 1 !
If you use 0 you put all the keys and values in the same bucket !

        System.out.println("14 hash of 12:" + d1Key.hashCode());
        System.out.println("15 hash of 13:" + d2.hashCode());

      
        System.out.println("14 contains");
        if(m.containsKey(d1Key)) {
            System.out.println("true");
        }

    }
}


hashcode in Dog is not overriden

run:
1 size:2
2 aString : k1
3 size:4
4 aString : null
5 aString : null
hash of aCat :12677476
6 size:5
7 aString : cat1
8 size:6
9 d1Value : clovervalue
10 size:6
11 d1Value : clovervalue1
12 d1Value() : clovervalue1
13 d1Value() : null
14 hash of 12:33263331
15 hash of 13:6413875
14 contains
true
BUILD SUCCESSFUL (total time: 0 seconds)

hashCode is and returns 0

run:
1 size:2
2 aString : k1
accessing method hashcode
accessing method hashcode
accessing method equals
3 size:4
accessing method hashcode
accessing method equals
accessing method equals
4 aString : dog1
accessing method hashcode
accessing method equals
5 aString : dog2
hash of aCat :11394033
6 size:5
7 aString : cat1
accessing method hashcode
accessing method equals
accessing method equals
8 size:6
accessing method hashcode
9 d1Value : clovervalue
10 size:6
accessing method hashcode
11 d1Value : clovervalue1
accessing method hashcode
12 d1Value() : clovervalue1
accessing method hashcode
accessing method equals
13 d1Value() : clovervalue1
accessing method hashcode
14 hash of 12:0
accessing method hashcode
15 hash of 13:0
14 contains
accessing method hashcode
true

hasCode is and returns name.lenght()

run:
1 size:2
2 aString : k1
accessing method hashcode
accessing method hashcode
accessing method equals
3 size:4
accessing method hashcode
accessing method equals
accessing method equals
4 aString : dog1
accessing method hashcode
accessing method equals
5 aString : dog2
hash of aCat :11394033
6 size:5
7 aString : cat1
accessing method hashcode
8 size:6
accessing method hashcode
9 d1Value : clovervalue
10 size:6
accessing method hashcode
11 d1Value : clovervalue1
accessing method hashcode
12 d1Value() : null
accessing method hashcode
13 d1Value() : null
accessing method hashcode
14 hash of 12:1
accessing method hashcode
15 hash of 13:1
14 contains
accessing method hashcode



Followers