Num1:同步访问共享的可变数据
关键字Synchronized
可以保证在同一时刻,只有一个线程可以执行某一个方法,或者某一个代码块。、
同步不仅仅理解为互斥的方式,如果没有同步,一个线程的变化就不能被其他线程看到。同步不仅可以阻止一个线程看到对象处于不一致的状态中,它还可以保证进入同步方法或者同步代码块的每个线程,都看到由同一个锁保护之前的所有修改效果。
基本版本:
public class StopThread { private static boolean stopRequested; private static synchronized void requestStop() { stopRequested = true; } private static synchronized boolean stopRequested() { return stopRequested; } public static void main(String[] args) throws InterruptedException { Thread backgroundThread = new Thread(new Runnable() { public void run() { int i = 0; while (!stopRequested()) i++; } }); backgroundThread.start(); TimeUnit.SECONDS.sleep(1); requestStop(); } }
改善版本:
public class StopThread { private static volatile boolean stopRequested; public static void main(String[] args) throws InterruptedException { Thread backgroundThread = new Thread(new Runnable() { public void run() { int i = 0; while (!stopRequested) i++; } }); backgroundThread.start(); TimeUnit.SECONDS.sleep(1); stopRequested = true; } }
简而言之,当多个线程共享可变数据的时候,每个读或者写数据的线程都必须执行同步。如果没有同步,就无法保证一个线程所做的修改可以被另一个线程获知,未能同步共享可变的数据或造成程序的活性失败和安全性失败。
Num2:executor和task优先于线程
如何创建一个工作队列呢,一行代码。
ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(runnable); executor.shutdown();
如果想让不止一个线程来处理来自这个队列的请求,只要调用一个不同的静态工厂,这个工厂创建了一种不同的executor service,称作线程池(thread pool)
。
Num3:慎用延迟初始化
延迟初始化是延迟到需要域的是值时才将它初始化的这种行为。如果永远不需要这个值,这个域就永远不会被初始化。这种方法既适用于静态域,也适用于实例域。虽然延迟初始化主要是一种优化,但它也可以用来打破类和实例初始化的有害循环。
在大多数情况下,正常的初始化要优先于延迟初始化。
- 如果利用延迟优化来破坏初始化的循环,就要使用同步的访问方法。
- 如果出于性能的考虑而需要对静态域使用延迟初始化,就用
lazy initialization holder class
模式。 - 如果出于性能的考虑而需要对实例域使用延迟初始化,就用双重检查模式
double-check idiom
。 单重检查模式
single-check idiom
。
示例代码:
public class Initialization { // Normal initialization of an instance field - Page 282 private final FieldType field1 = computeFieldValue(); // Lazy initialization of instance field - synchronized accessor - Page 282 private FieldType field2; synchronized FieldType getField2() { if (field2 == null) field2 = computeFieldValue(); return field2; } // Lazy initialization holder class idiom for static fields - Page 283 private static class FieldHolder { static final FieldType field = computeFieldValue(); } static FieldType getField3() { return FieldHolder.field; } // Double-check idiom for lazy initialization of instance fields - Page 283 private volatile FieldType field4; FieldType getField4() { FieldType result = field4; if (result == null) { // First check (no locking) synchronized (this) { result = field4; if (result == null) // Second check (with locking) field4 = result = computeFieldValue(); } } return result; } // Single-check idiom - can cause repeated initialization! - Page 284 private volatile FieldType field5; private FieldType getField5() { FieldType result = field5; if (result == null) field5 = result = computeFieldValue(); return result; } private static FieldType computeFieldValue() { return new FieldType(); } } class FieldType { }
来源:https://www.cnblogs.com/cr330326/p/5623289.html