zoukankan      html  css  js  c++  java
  • 【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 {
    }
    
  • 相关阅读:
    ubuntu linux切换用户到root
    passwd命令
    如何根据驱动程序及其安装文件来访问该设备[转]
    CMMI的5个级别和25个过程域
    Linux操作系统启动过程
    VMWare上网三种工作模式
    卷积的意义【转】
    Linux内核模块动态添加方法
    Linux内核编译的过程
    mysql存入中文乱码解决方法(windows环境)
  • 原文地址:https://www.cnblogs.com/cr330326/p/5623289.html
Copyright © 2011-2022 走看看