Sunday, December 19, 2010

Call me!


Today you will have a great occasion to call someone you would never expect to call... a thread. We talked already about the concurrency on the blog: Threads part 1: The basics and Threads part 2: functions overview. But the problem with the previous solution to achieve simultaneous computation is the lack of explicit mechanism to retrieve the result from a thread. As luck would have it, since Java 1.5 we have an access to a new interface – Callable. In comparison to Runnable there are a few significant differences:
  • with Callable you can easily return a result of another execution thread.
  • with Callable you can throw checked exceptions.
  • with Callable you have to use a thread executor.
So far so good. Now, to get more familiar with it, let's have a look at some code:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;


class Computation implements Callable<Integer> {

@Override
public Integer call() throws Exception {
int result = 0;
for(int i = 0; i < 10000; i++) {
for(int j = 0; j < 100000; j++) {
// Some taught computation
result += (i * j) - (i * j) + 1;
}
}
return result;
}

}

public class CallableExample {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(5);
Future<Integer> f1 = pool.submit(new Computation());
for(int i = 0; i < 10; i++) {
System.out.println(i);
}
try {
System.out.println(f1.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
pool.shutdown();
}
}

Ok, there are a few new elements regarding Callable. First of all, if we implement the Callable interface, we have to implement T call() method. This is where the action takes place, it's a method corresponding to the run() method from Runnable interface. And the other important thing – it's the place where we can throw an exception (Exception or any subclass).
When the class implementing Callable interface is ready, we can instantiate it and run through a submit() method of a thread executor what happens in line 27. The submit() method will return some implementation of a Future interface. It represents the thread's computation and provides a few useful methods, among others:
boolean isDone();
which returns true if the task is completed.
T get()
which returns a result of a task of type T, or if the task is not completed yet it waits until it's finished. Actually this could be achieved with a wait() method using a Runnable interface and calling it on the instance of a thread from the main execution thread.

And that's it. I'm sure that the above information and the sample code will let you use the Callable interface in appropriate way.

Wednesday, December 15, 2010

Type erasure in Java.

Probably every Java developer knows what type erasure is. In Oracle tutorial on Type Erasure we can read:

When a generic type is instantiated, the compiler translates those types by a technique called type erasure — a process where the compiler removes all information related to type parameters and type arguments within a class or method. Type erasure enables Java applications that use generics to maintain binary compatibility with Java libraries and applications that were created before generics.

The generic types are only for the compile time - after the type checking they are removed and gone for good, for sake of legacy code. Are they really? Let's have a look at the code I just wrote:

import java.lang.reflect.Field;   
import java.lang.reflect.ParameterizedType;   
import java.lang.reflect.Type;   
  
class P1 {}   
class P2 {}   
class P3 {}   
  
class A<T1, T2, T3> { }   
  
public class Gen2 {    

    A<P1, Integer, P3> genTest = new A<P1, Integer, P3>();   
    public static void main(String[] args) throws Exception {      
        ParameterizedType genTestField = (ParameterizedType)Gen2.class.getDeclaredField("genTest").getGenericType();   
        for(Type type : genTestField.getActualTypeArguments() ) {   
            System.out.println(type);   
        }   
    }   


In the above code, we define a generic class A that can be parametrized - in the line 13 we instantiate this class with parameters P1, Integer and P3. And now,
through a reflection of Gen2 class and methods getDeclaredField(String) and getGenericType() we can elicit the parameters used during instantiating generic class A!
The code will print:
class P1
class java.lang.Integer
class P3
So in this way we can get exactly the generic parameters that were used. How this can be accomplished? As I already wrote, through a reflection. When we open a compiled Gen2.class file we can see a section "Signature":
Signature LA<LP1;Ljava/lang/Integer;LP3;>;
which shows the types that we were interested in. So apparently it seems that this information is not completely removed after the compilation time. From the bytecode yes, but in the .class file the information is still available!
In my opinion it's a very interesting and important example especially when we can read in many places that after the compilation we can't get the parameters anymore! Hope it was at least a little bit inspiring and encouraged you to read more on the reflection mechanism.

Saturday, December 11, 2010

String's split() method.


This will be short. Recently I had to use this simple String class method when developing a parser for some pdf documents. Everything was going well until one moment. In the document, among others I had to elicit a range value which was given in the format x..y (for instance, 1..32). After getting the string 1..32 I wanted to use split method to separate the bounds. So in the code it could look like this:


String range = "1..32";
String[] bounds = range.split("..");

But that didn't work! Why? The answer is very simple. The String's split method takes a regex expression as an argument! And in Java "." (a dot) in regex means any character. So that's why the returned array was empty! To solve it we have to use "\\" between any special regex character if we want it to be treated as a string character. So we should change the above code to:


String range = "1..32";
String[] bounds = range.split("\\.\\.");

That's simple! So remember: split's argument = regex expression! Wish all my readers remember this both on the exam and during the work with Java code.