diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..a7d05258 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target/ +/.idea/* diff --git a/.java-version b/.java-version new file mode 100644 index 00000000..62593409 --- /dev/null +++ b/.java-version @@ -0,0 +1 @@ +1.8 diff --git a/Chapter11/P220_ThreadLocal/src/modern/challenge/Main.java b/Chapter11/P220_ThreadLocal/src/modern/challenge/Main.java index 07154094..405a15ef 100644 --- a/Chapter11/P220_ThreadLocal/src/modern/challenge/Main.java +++ b/Chapter11/P220_ThreadLocal/src/modern/challenge/Main.java @@ -4,14 +4,21 @@ public class Main { public static void main(String[] args) throws InterruptedException { - System.setProperty("java.util.logging.SimpleFormatter.format", - "[%1$tT] [%4$-7s] %5$s %n"); + ThreadSafeStringBuilder safe = new ThreadSafeStringBuilder(); - ThreadSafeStringBuilder threadSafe = new ThreadSafeStringBuilder(); + for (int i = 0; i < 2; i++) { + new Thread(safe, "[Example1-thread-" + i+"]").start(); + // INFO: FINISH -> [Example1-thread-0] [Local-thread-safe[Example1-thread-0]] + // INFO: FINISH -> [Example1-thread-1] [Local-thread-safe[Example1-thread-1]] + } - for (int i = 0; i < 3; i++) { - new Thread(threadSafe, "thread-" + i).start(); - } + UnsafeStringBuilder unSafe = new UnsafeStringBuilder(); + + for (int i = 0; i < 2; i++) { + new Thread(unSafe, "[Example2-thread-" + i+"]").start(); + // INFO: FINISH -> [Example2-thread-1] [Local-thread-unsafe[Example2-thread-1]] + // INFO: FINISH -> [Example2-thread-0] [Local-thread-unsafe[Example2-thread-1][Example2-thread-0]] + } } } diff --git a/Chapter11/P220_ThreadLocal/src/modern/challenge/ThreadSafeStringBuilder.java b/Chapter11/P220_ThreadLocal/src/modern/challenge/ThreadSafeStringBuilder.java index b253c82c..8850fe4d 100644 --- a/Chapter11/P220_ThreadLocal/src/modern/challenge/ThreadSafeStringBuilder.java +++ b/Chapter11/P220_ThreadLocal/src/modern/challenge/ThreadSafeStringBuilder.java @@ -3,39 +3,30 @@ import java.util.Random; import java.util.logging.Logger; -public class ThreadSafeStringBuilder implements Runnable { +class ThreadSafeStringBuilder implements Runnable { private static final Logger logger = Logger.getLogger(ThreadSafeStringBuilder.class.getName()); - private static final Random rnd = new Random(); - private static final ThreadLocal threadLocal - = ThreadLocal.withInitial(() -> { - return new StringBuilder("Thread-safe "); - }); + private static final ThreadLocal threadSafe = ThreadLocal.withInitial(() -> { + return new StringBuilder("Local-thread-safe"); // Creates a local instance only the current thread has access to + }); + @Override public void run() { - logger.info(() -> "-> " + Thread.currentThread().getName() - + " [" + threadLocal.get() + "]"); try { - Thread.sleep(rnd.nextInt(2000)); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - logger.severe(() -> "Exception: " + ex); + Thread.sleep(new Random().nextInt(2000)); + } catch (InterruptedException e) { + throw new RuntimeException(e); } - // threadLocal.set(new StringBuilder(Thread.currentThread().getName())); - threadLocal.get().append(Thread.currentThread().getName()); + // Here we got the String Builder, but each local Thread gets a local copy + threadSafe.get().append(Thread.currentThread().getName()); - logger.info(() -> "-> " + Thread.currentThread().getName() - + " [" + threadLocal.get() + "]"); + logger.info(() -> " FINISH -> " + Thread.currentThread().getName()+ " [" + threadSafe.get() + "]"); - threadLocal.set(null); - // threadLocal.remove(); + threadSafe.set(null); - logger.info(() -> "-> " + Thread.currentThread().getName() - + " [" + threadLocal.get() + "]"); } - } diff --git a/Chapter11/P220_ThreadLocal/src/modern/challenge/UnsafeStringBuilder.java b/Chapter11/P220_ThreadLocal/src/modern/challenge/UnsafeStringBuilder.java new file mode 100644 index 00000000..fa06ba22 --- /dev/null +++ b/Chapter11/P220_ThreadLocal/src/modern/challenge/UnsafeStringBuilder.java @@ -0,0 +1,27 @@ +package modern.challenge; + +import java.util.Random; +import java.util.logging.Logger; + +class UnsafeStringBuilder implements Runnable { + + private static final Logger logger = Logger.getLogger(ThreadSafeStringBuilder.class.getName()); + + private static final StringBuilder threadLocal = new StringBuilder("Local-thread-unsafe"); + + @Override + public void run() { + + try { + Thread.sleep(new Random().nextInt(2000)); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + // Here we got the String Builder, but each local Thread gets a local copy + threadLocal.append(Thread.currentThread().getName()); + + logger.info(() -> " FINISH -> " + Thread.currentThread().getName()+ " [" + threadLocal + "]"); + } + +}