January 22, 2009

Java Concurrency

Writing a thread safe application is a challenging task, but with Java 1.5 and 1.6 a lot of the plumbing infrastructure has been moved into the Java language. But before looking at these new feature, one must first be able to write thread safe classes. Writing thread safe classes is most about sharing object's state in a safe way. That can be achieved in four ways:

  • Use Thread Confinement, that is to ensure that data is only accessed by one thread at a time. Examples of that are:

    • Swing Event Dispatch Thread, that is accessed via the javax.swing.SwingWorker
    • java.sql.Connection that is retrieved from a server application pool.

  • Use Read-Only data.

  • Make object thread safe.

    • java.util.concurrent.atomic.AtomicLong

    • java.util.concurrent.ConcurrentHashMap

    • java.util.concurrent.ConcurrentLinkedQueue

    • java.util.concurrent.CopyOnWriteArrayList is the concurrent replacement of . java.util.Collections.synchronizedList(), but should only be used when iteration is far more common than modification. The reason is that copying arrays becomes very costly when the size of the list grows.

  • Guard object.

    • synchronized methods

    • Intrinsic Lock: Using private class variable to synchronize blocks in methods.

  • If you are not depending of the previous value of a variable, you can get away of adding volatile to the class variable. Volatile ensures that the most recent values are always visible between different threads memory areas. Using volatile can simplify implementing thread safety, but beware that volatile only guarantee visibility, not Atomicity.


Now to show all the goodies that the latest Java comes with. If you want to move out one task of a code that could be done asynchronously, you need a Producer-Consumer. The Producer is the original code and the asynchronously task is put in the Consumer.

public class Producer implements Runnable {

private final File root;

private final BlockingQueue queue;

public Producer(String path, BlockingQueue queue) {
this.root = new File(path);
this.queue = queue;
}

@Override
public void run() {
for (File file : root.listFiles()) {
if (file.isFile()) {
readHeadOfFile(file);
}
}
System.out.println("Finished producing!");
}

public void readHeadOfFile(File file) {
System.out.println("Reading '" + file.getName() + "'...");
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
queue.add(reader.readLine());
} catch (IOException e) {
System.out.println("Failed to read '" + file.getAbsolutePath() + "'. " + e.getMessage());
Thread.currentThread().interrupt();
} finally {
closeQuitly(reader);
}
}

public void closeQuitly(Reader reader) {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
}
}
}
}

public class Consumer implements Runnable {

private final BlockingQueue queue;

public Consumer(BlockingQueue queue) {
this.queue = queue;
}

@Override
public void run() {
try {
while (true) {
String str = queue.take();
System.out.println("Consuming '" + str + "'.");
}
} catch (InterruptedException e) {
System.out.println("Consumer interrupted!");
Thread.currentThread().interrupt();
}
}
}

public class ProducerConsumerTest {

private final ExecutorService pool = Executors.newFixedThreadPool(10);

private final BlockingQueue queue = new LinkedBlockingQueue();

@Before
public void setUp() {

}

@After
public void tearDown() {
pool.shutdown(); // Disable new tasks from being submitted
try {
System.out.println("Wait 30s for existing tasks to terminate...");
if (!pool.awaitTermination(30, TimeUnit.SECONDS)) {
System.out.println("Cancel currently executing tasks");
pool.shutdownNow();
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}

@Test
public void test() {
try {
pool.execute(new Producer("/home/magnus/documents/", queue));
pool.execute(new Consumer(queue));
} catch (Exception e) {
e.printStackTrace();
pool.shutdown();
}
}
}

Examples of applicable scenarios are:

  • Moving logic operation out from the IO code.

  • Moving logging code out of the logic code.


Another convenient function is a Latch. I used it when writing a test harness and wanted to make sure all the test threads were released at the same time and then wait for them to finish, before exiting the test harness.
See java.util.concurrent.CountDownLatch API for a good example.

If you want a reusable Latch, then look at java.util.concurrent.CyclicBarrier. I used that one when doing calculation that should take place every time unit. See the API for a good example.

One of the best thing that comes out of the box are all the Thread Pools:

  • java.util.concurrent.Executors.newFixedThreadPool

  • java.util.concurrent.Executors.newCacheThreadPool

  • java.util.concurrent.Executors.newSingleThreadPool. Good because if single thread goes down a new one is automatically started.

  • java.util.concurrent.Executors.newScheduledThreadPool

January 20, 2009

Firefox freezes when oping grails.org

I had my first real bad experience with Ubuntu when I was looking at the grails project. The Firfox web browser totally hanged when opened grails.org. I have google around but could not directly find any solution to this problem, but yesterday I found a bug report about it. It is the nvidia graphical drivers that is not working properly. To fix this install a newer nvidia driver:

sudo apt-get install nvidia-180-kernel-source nvidia-180-modaliases nvidia-glx-180

This will remove the old drivers:

nvidia-177-kernel-source
nvidia-glx-177


After installation reboot and after login should "Hardware Drivers" dialog appear and prompt you to grant that restricted drivers be used. Select the new nvidia 180 drivers.

https://bugs.launchpad.net/ubuntu/+source/nvidia-graphics-drivers-177/+bug/289964

January 2, 2009

Removing White Spaces in File Name

Sometimes when you are transferring files to or from different devices or even computer running different OS, using spaces in file names can cause problems. Therefore I wrote this little script that removes white spaces from all the files in a given directory.

#!/bin/sh
for f in *; do mv "$f" `echo $f | tr --delete ' '`; done

Using Different Date and Time Format in Thunderbird

If you are running a non-localized Ubuntu installation, but going crazy on the America date and time format in Thunderbird, then you should use this script to start Thunderbird. The script alter the date and time format to yyyy-MM-dd.

#!/bin/sh
export LC_TIME=en_DK.utf8
/usr/bin/thunderbird $*

Playing Commercial DVD with Ubuntu

Like Adobe Flash and proprietary media formats cannot be distributed with Ubuntu since they are not open source, but playing commercial DVD on Ubuntu is not hard. Simply install the below script and you will be able to play commercial DVD.

sudo /usr/share/doc/libdvdread3/install-css.sh

Once the scripts has finished simply insert a DVD and Totem player will automatically be launch. One downside with Totem player is it is not handling DVD menu very well, actually you could say it does not handle it at all. A better choice is then using VLC for playing DVD.

sudo apt-get install vlc

January 1, 2009

Building Standalone Application with Maven2

If you are building standalone application in Java, Maven is your friend when packing your application, There are two way to let Maven package your application, either as a single jar with all your dependencies jar.


<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>


One advantage if you choose to do this way is if you need to sign your application jar. This is needed if you are building a Java Web Start client and you need more access than connecting back to the server. To read more about have Maven signing your jar read http://maven.apache.org/plugins/maven-jar-plugin/usage.html.
But if you choose to go this way, make sure that all license agreement are shipped with your one single jar.

Another way is to let Maven package your source code only and then referring the dependent jar file from the MANIFEST file.


<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>se.msc.adapter.Main</mainClass>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>

Listening on Internet Radio with Ubuntu

Listening on Internet Radio while programming is a must, but the common player with Ubuntu, Rythmbox Music Player, does not have many preinstalled internet radio stations. Of course is there way to fix this, the below site shows you have to add the popoular swedish internet radio stations radioseven.se to Rythmbox.

http://henrikan.wordpress.com/2008/02/29/svenska-internetradiokanaler-for-rhythmbox/

But a better player that have SHOUTcast search engine preinstalled, which is the same search engine that ships with Winamp, is StreamTuner. The SHOUTcast search engine can almost find any internet radio station that will satisfy almost all music flavor.

And as always Ubuntu shine when it comes to install new programs.

sudo apt-get install streamtuner streamripper