Java Secret: InheritableThreadLocal

Overview

If you follow functional programming methodologies, every dependency for a function is passed to it including all dependencies of the functions its calls etc. This model can work very well because it makes it clear all the values which a piece of code depends on.

However, it can mean passing dependencies through code which shouldn't need to know about these values. (Or in fact cannot be changed to include them)

Using a ThreadLocal

A way to avoid passing values over level of calls which don't know anything about them is to use a ThreadLocal. This allows you to set a value which is available at any point in the call stack in a thread safe way. Its like passing a ball into the air you want to run and catch later.

static final ThreadLocal userName = new ThreadLocal();

public static void main(String... args) {
    userName.set("Jane");
    Runnable run = new Runnable() {
        @Override
        public void run() {
            String threadName = Thread.currentThread().getName();
            String name = userName.get();
            System.out.println(threadName +": Welcome "+name);
        }
    };
    run.run();
}
prints
main: Welcome Jane

As you can see I can set a value I don't want or cannot pass as an argument.

InheritableThreadLocal

However, say I want to be able to sporn threads and still keep the value. In this case you can use an InheritableThreadLocal which passes the value to child threads.

static final ThreadLocal userName = new InheritableThreadLocal();

public static void main(String... args) {
    userName.set("Jane");
    Runnable run = new Runnable() {
        @Override
        public void run() {
            String threadName = Thread.currentThread().getName();
            String name = userName.get();
            System.out.println(threadName +": Welcome "+name);
        }
    };
    new Thread(run).start();
}
prints
thread-0: Welcome Jane

Comments

  1. In the first sample using ThreadLocal, In the code it run as:
    run.run();
    It does not seems to be run in a new thread so the context was run at same thread.
    If use new Thread(run).start(), the context run in different thread, the out put should be null.

    ReplyDelete
    Replies
    1. This is correct. If you use ThreadLocal and run in a different thread it would be null which is why it is not run in a different thread.

      Delete
  2. awful and completely wrong example

    ReplyDelete
    Replies
    1. Can you clarify what you mean? Are you saying that the code doesn't do what the post says?

      Delete

Post a Comment

Popular posts from this blog

Low Latency Microservices, A Retrospective

Unusual Java: StackTrace Extends Throwable

System wide unique nanosecond timestamps