Friday, July 31, 2020

Java random notes for quick reference


Lambda & CheckedException/RuntimeException
If you try to use methods that throw any checked exception in a Lamda expression - it will complain - one solution is to change to /use custom RuntimeException instead of checked exception

SimpleDateFormat is not thread-safe: WHY? - Alternatives?

SDF keeps intermediate results in instance fields (Calendar) - so if one instance is used by 2 threads, can mess it.

Sample:
DateTimeFormatValidator{
private SimpleDateFormat sdf = null; //NOT thread safe

          private DateTimeFormatter formatter = null;//thread safe

private org.apache.commons.lang3.FastDateFormat fdf = null;//thread safe

public void inititialize(String formatStr){ 

    //sdf = new SimpleDateFormat(formatStr);

             formatter = DateTimeFormatter.ofPattern(formatStr);

public boolean isValidFormat(Object dateStr){
    sdf.format(dateStr);// not thread safe

    formatter.parse(dateStr); //thread safe

}
}


Java WebApps - UnsatisfiedLinkError - native library


As of Tomcat versions 9.0.138.5.35, and 7.0.92 we have added the following options to address this issue BZ-62830:

1) Use the JniLifecycleListener to load the native library.

e.g. to load the opencv_java343 library, you can use:

<Listener className="org.apache.catalina.core.JniLifecycleListener"
          libraryName="opencv_java343" />

2) Use the load() or loadLibrary() from org.apache.tomcat.jni.Library instead of System.

e.g.

org.apache.tomcat.jni.Library.loadLibrary("opencv_java343");

Using either of those options will use the Common ClassLoader to load the native library, and therefore it will be available to all of the Web Apps.

Java 8 - Streams


Java Process - Fire and Forget


Process p = Runtime.getRuntime().exec( "command" );
p.waitFor(); // current thread will wait until the process "p" is completed/interrupted.



Threads - the old way - t1.start() , t1.join();

/**
 * Call 2 expensive methods on separate threads 
 *    
 * @throws InterruptedException 
 */
public void doMultiThreadedJob() throws InterruptedException {
  /* create Runnable using anonymous inner class */
  Thread t1 = new Thread(new Runnable() { 
    public void run() {
      System.out.println("starting expensive task thread t1");
      doSomethingExpensive(); 
      System.out.println("finished expensive task thread t1");
    }
  });
  /* start processing on new threads */
  t1.start();
  /* block current thread until t1 has finished */
  t1.join();
}

Dealing with threads directly can be cumbersome, so Oracle simplified things by providing a layer of abstraction via its Executor API. An Executor allows you to process tasks asynchronously without having to deal with threads directly.

The Executors factory class is used to create an instance of an Executor, either an ExecutorService or an ScheduledExecutorServiceSome of the most common types of Executor are described below.
  • Executors.newCachedThreadPool() — An ExecutorService with a thread pool that creates new threads as required but reuses previously created threads as they become available.
  • Executors.newFixedThreadPool(int numThreads) — An ExecutorServicethat has a thread pool with a fixed number of threads. The numThreads parameter is the maximum number of threads that can be active in the ExecutorService at any one time. If the number of requests submitted to the pool exceeds the pool size, requests are queued until a thread becomes available.
  • Executors.newScheduledThreadPool(int numThreads) — A ScheduledExecutorServicewith a thread pool that is used to run tasks periodically or after a specified delay.
  • Executors.newSingleThreadExecutor() — An ExecutorService with a single thread. Tasks submitted will be executed one at a time and in the order submitted.
  • Executors.newSingleThreadScheduledExecutor() — An ExecutorService that uses a single thread to execute tasks periodically or after a specified delay.

execute(Runnable)

The execute method takes a Runnable and is useful when you want to run a task and are not concerned about checking its status or obtaining a result. Think of it as fire and forget asynchronous task.
executorService.execute(()->{
  System.out.println(String.format("starting expensive task thread %s", Thread.currentThread().getName()));
  doSomethingExpensive();    
}

Future<?> submit(Runnable)

Like execute(), the submit() method also takes a Runnable but differs from execute()because it returns a Future. A Future is an object that represents the pending response from an asynchronous task. Think of it as a handle that can be used to check the status of the task or retrieve its result when the task completes. Futures use generics to allow you to specify the return type of the task. However, given that the Runnablerun() method has the return type void, the Future holds the status of the task rather than a pending result. This is represented as Future<?> in the example below.
Future<?> taskStatus = executorService.submit(()->{
  System.out.println(String.format("starting expensive task thread %s", Thread.currentThread().getName()));
  doSomethingExpensive();    
}

Thesubmit(Runnable)method is useful when you want to run a task that doesn't return a value but you'd like to check the status of the task after it's been submitted to the ExecutorService.

Checking the Status of a Task

Future has a few useful methods for checking the status of a task that's been submitted to the ExecutorService.
  • isCancelled() checks if the submitted task has already been canceled.
  • isDone() checks if the submitted task has already completed. When a task has finished, isDone will return true whether the task completed successfully, unsuccessfully, or was canceled.
  • cancel() cancels the submitted task. A boolean parameter specifies whether or not the task should be interrupted if it has already started.
/* check if both tasks have completed - if not sleep current thread 
 * for 1 second and check again
 */
while(!task1Future.isDone() || !task2Future.isDone()){
  System.out.println("Task 1 and Task 2 are not yet complete....sleeping");
  Thread.sleep(1000);
}
Future<T> submit(Callable)
The submitmethod is overloaded to take a Callable as well as a Runnable. Like a Runnable, a Callable represents a task that is executed on another thread. A Callable differs from a Runable because it returns a value and can throw a checked Exception. The Callable interface has a single abstract method public T call() throws Exception and like Runable can be implemented with an anonymous inner class or lambda. The return type of the call() method is used to type the Future returned by the ExecutorService. Two code snippets below show how a Callable can be created via an anonymous inner class and a lambda expression.
Future<Double> task1Future = executorService.submit(new Callable<Double>() {
  public Double call() throws Exception {
    System.out.println(String.format("starting expensive task thread %s", 
        Thread.currentThread().getName()));
    Double returnedValue = someExpensiveRemoteCall();
    return returnedValue;
  } 
});
Future<Double> task2Future = executorService.submit(()->{
  System.out.println(String.format("starting expensive task thread %s", Thread.currentThread().getName()));
  Double returnedValue = someExpensiveRemoteCall();
  return returnedValue;
});

Both examples create a Callable and pass it to the execute method. The Callable is executed as soon as a thread is available.

Getting a Result from a Future

When a Callable is submitted to the ExecutorService, we receive a Future with the return type of the call() method. In the example above, call() returns a Double so we get a Future<Double>. One way of retrieving the result from a Future is by calling its get() method. get() will block indefinitely waiting on the submitted task to complete. If the task doesn't complete or takes a long time to complete, the main application thread will remain blocked.
Waiting indefinitely for a result is usually not ideal. We'd rather have more control over how we retrieve the result and take some action if a task doesn't complete within a certain amount of time. Luckily there's an overloaded get(long timeout, TimeUnit unit) method that waits for the specified period of time and if the task hasn't finished (result not available), throws a TimeoutException.
Double value1 = task1Future.get();
Double value2 = task2Future.get(4,  TimeUnit.SECONDS); // throws TimeoutException

Submitting Multiple Callables


Builder Pattern

The builder pattern is a good choice when designing classes whose constructors or static factories would have more than a handful of parameters.


Private constructor, builder class , with setter returning builder obj, helps to chain the setters














No comments:

Post a Comment