Tuesday, 19 April 2016

Effective Java Item 71: Lazy initialization, holder class, double checking

static field uses holder class

 private static class ValueHolder{  
     static final String value = "Lazy initialized";  
   }  
   
   public static String getValue(){  
     return ValueHolder.value;  
   }  

instance field uses double check

 private volatile String value;  
   
   public String getValue(){  
     String result = value;  
     if (result == null){  
       synchronized (this){  
         result = value;  
         if (result == null){  
           value = result = "LazyInitialized";  
         }  
       }  
     }  
     return result;  
   }  

if you don't mind re-creating instance again, You can use single check

 public String getValue(){  
     String result = value;  
     if (result == null){  
       value = result = "LazyInitialized";  
     }  
     return result;  
   }  

Monday, 18 April 2016

Effective Java Item 69: Synchronized map vs ConcurrentMap

Synchronized map

 public static void main(String[] args){  
     Map<String, String> syncMap = Collections.synchronizedMap(new HashMap<String, String>());  
     syncMap.put("1","1");  
     syncMap.put("2","2");  
     syncMap.put("3","3");  
     for (String key : syncMap.keySet()){  
       addValue(syncMap);  
     }  
   }  
   
   private static void addValue(Map<String, String> map){  
     map.put("4", "4");  
   }  

Throws ConcurrentModificationException

 Exception in thread "main" java.util.ConcurrentModificationException  
      at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429)  
      at java.util.HashMap$KeyIterator.next(HashMap.java:1453)  

ConcurrentHashMap never throws ConcurrentModificationException

 Map<String, String> syncMap = new ConcurrentHashMap<>();  

Sunday, 17 April 2016

Effective Java Item 66: Volatile, synchronization, and AtomicLong

volatile

 class SerialNumber{  
   private static volatile long nextSerialNumber = 0;  
   
   public static long nextSerialNumber(){  
     return nextSerialNumber++;  
   }  
 }  
   
 public class MyConcurrency extends Thread{  
   
   private static List<Long> numbers = new ArrayList<>();  
   
   private static synchronized void add(long number){  
     numbers.add(number);  
   }  
   
   public static void main(String[] args) throws Exception{  
     new MyConcurrency().start();  
     new MyConcurrency().start();  
     new MyConcurrency().start();  
     Thread.sleep(10*1000); //Make sure threads all end  
     Set<Long> hashSet = new HashSet<>();  
     for(long i : numbers) {  
       if(!hashSet.add(i)){  
         System.out.println("Has duplicate "+i);  
       }  
     }  
     System.out.println("Finish");  
   }  
   
   @Override  
   public void run() {  
     long nextSerialNumber;  
     do{  
       nextSerialNumber = SerialNumber.nextSerialNumber();  
       add(nextSerialNumber);  
     }while(nextSerialNumber < 10000);  
   }  
 }  

Found duplicates

 Has duplicate 4528  
 Has duplicate 5280  
 Has duplicate 7274  
 Has duplicate 9376  
 Finish  

Correct implementation using synchronized

 class SerialNumber{  
   private static long nextSerialNumber = 0;  
   
   public static synchronized long nextSerialNumber(){  
     return nextSerialNumber++;  
   }  
 }  

Correct implementation using AtomicLong

 class SerialNumber{  
   private static final AtomicLong nextSerialNumber = new AtomicLong();  
   
   public static long nextSerialNumber(){  
     return nextSerialNumber.getAndIncrement();  
   }  
 }  

Saturday, 16 April 2016

Threadlocal example

Business layer can access userId without passing the parameter from web layer.

 
 package threadlocal;  
   
 class SecurityContext {  
   
   private String userId = null;  
   
   public String getUserId() {  
     return userId;  
   }  
   
   public void setUserId(String userId) {  
     this.userId = userId;  
   }  
 }  
   
 class MyThreadLocal {  
   private static final ThreadLocal userThreadLocal = new ThreadLocal();  
   
   public static void set(SecurityContext user) {  
     userThreadLocal.set(user);  
   }  
   
   public static void unset() {  
     userThreadLocal.remove();  
   }  
   
   public static SecurityContext get() {  
     return (SecurityContext)userThreadLocal.get();  
   }  
 }  
   
 class BusinessService {  
   
   public void businessMethod() {  
     SecurityContext securityContext = MyThreadLocal.get();  
     System.out.println(securityContext.getUserId());  
   }  
 }  
   
 public class Main extends Thread{  
   public static void main(String[] args){  
     new Main().start();  
     new Main().start();  
   }  
   
   @Override  
   public void run() {  
     SecurityContext securityContext = new SecurityContext();  
     securityContext.setUserId(getName());  
     MyThreadLocal.set(securityContext);  
     new BusinessService().businessMethod();  
     MyThreadLocal.unset();  
   }  
 }  
   
Reference: http://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/

Effective Java Item 49: Auto boxed type NullPointerException

Seems quite innocuous, but throws NPE

Example 1

   public static void main(String[] args){  
     Boolean b = null;  
     call(b);  
   }  
   
   public static void call(boolean b){  
     System.out.println(b);  
   }  

Example 2

   public static void main(String[] args){  
     Integer i = null;  
     if (i == 42){  
       System.out.println(i);  
     }  
   }  

Thursday, 14 April 2016

jQuery return false; vs e.preventDefault()

return false;

is equal to

e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();

So the lesson is never use 'return false' unless you completely understand it.

Reference: http://fuelyourcoding.com/jquery-events-stop-misusing-return-false/comment-page-2/#comment-73556

Monday, 11 April 2016

Bash script to replace part of file name

Suppose a folder has following files

abcde-l1.mp3 abcde-l2.mp3 abcde-l3.mp3 abcde.meta.xml abcde.wav

We want to rename them to

12345-l1.mp3 12345-l2.mp3 12345-l3.mp3 12345.meta.xml 12345.wav

 #!/bin/bash  
   
 if [[ ! $1 ]]; then  
   echo "No argument supplied"  
   exit 1  
 fi  
   
 newname=$1  
   
 for entry in /Users/msun/msun/sound/*.wav; do  
  #Get file name without path e.g. abc.wav  
  filename=$(basename $entry)  
  #Get file name without extension e.g. abc  
  filename="${filename%.*}"  
  break   
 done  
   
 #replace $filename with $newname  
 for entry in /Users/msun/msun/sound/*; do  
  mv $entry ${entry/$filename/$newname}  
 done