【Java基础】并发

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