JUC基础知识篇

java并发实战 -- JUC线程高级

##1.volatile关键字-内存可见性 内存可见性问题是,当多个线程操做共享数据时,彼此不可见。<br/> volatile关键字:当多个线程操做共享数据时,能够保存内存中的数据是可见的。相较于synchronized是一种较为轻量级的同步策略。<br> 注意:<br>html

  1. volatile 不具有互斥性<br>
  2. volatile不能保证变量的原子性

##2.原子变量-CAS算法 ###i++的原子性问题: i++的操做实际上分为三个步骤"读-改-写"。 1 int i = 10; 2 i = i++;//10java

1 int temp = i;
2 i = i + 1;
3 i = temp;

###原子变量:jdk1.5后java.util.concurrent.atomic包下提供了经常使用的原子变量: 1.volatile保证内存可见性<br/> 2.CAS(Compare-And - Swap)算法保证数据的原子性<br/>  CAS 算法是硬件对于并发操做共享数据的支持<br/>  CAS 包含了三个操做数:<br/>   内存值V<br/>   预估值A<br/>   更新值B<br/> 当且仅当 V == A时,V = B,不然,将不作任何操做。算法

##3.ConcurrentHashMap锁分段机制 java5.0 在java.util.concurrent包中提供了多种并发容器类来改进同步容器的性能。<br> ConcurrentHashMap 同步容器类是java5增长的一个线程安全的哈希表。内部采用“锁分段”机制替代Hashtable的独占锁,进而提升性能。<br/> 此包还提供了设计用于多线程上下文中的Collection实现: ConcurrentHashMap、ConcurrentSkipListMap、ConcurrentSkipListSet、CopyOnWriteArrayList、CopyOnWriteArraySet。当指望许多线程访问一个给定collection时,ConcurrentHashMap 一般优于同步的HashMap,ConcurrentSkipListMap一般优于同步的TreeMap。当指望的读数和遍历远远大于列表的更新数时,CopyOnWriteArrayList优于同步的ArrayList。缓存

##4.CountDownLatch闭锁 闭锁:一个同步辅助类,在完成某些运算时,只有其余全部线程的运算所有完成,当前运算才继续执行安全

##5.实现Callable接口 **java5.0以后提供了一个新的建立执行线程的方式:Callable接口。 Callable须要依赖FutureTask,FutureTask也能够用做闭锁。 Callable与Runnable的异同点<br>多线程

  1. 二者都是为那些其实例可能被另外一个线程执行的类设计的<br>
  2. Runnable不会返回结果,而且没法抛出通过检查的异常<br>**

##6.Lock同步锁 用于解决多线程安全问题的方式:<br> synchronized:<br>并发

  1. 同步代码块<br>
  2. 同步方法<br> jdk1.5后<br>
  3. 同步锁Lock<br> 注意:这是一个显示锁,须要经过lock()方法上锁,必须经过unlock()方法进行释放锁。<br> ReentranLock实现了Lock接口,并提供了与synchronized相同的互斥性和内存可见性。但相较于synchronized提供了更高的处理锁的灵活性。
    ##7.Condition控制线程通讯 Cndition接口描述了可能会与锁有关联的条件变量。这些变量在用法上与使用Object.wait访问的隐式监视器相似,但提供了更强大的功能。须要特别指出的是,单个Lock可能与多个Condition对象关联。<br> 在condition对象中,方法分别为await、signal、signalAll。(与咱们在操做系统中线程同步章节所学的十分类似。)<br> Condition实例实质上被绑定到一个锁上。要为特定Lock实例得到Condition实例,请使用newCondition()方法。 ##8.线程八锁 因为内容太多,只能写个总结。<br> 线程八锁的关键<br> ①非静态方法的锁默认为实例对象自己,静态方法的锁为对应的类对象自己<br> ②某一个时刻内,只能有一个线程持有锁,不管几个方法。

##9.线程按序交替 编写一个程序,开启 3 个线程,这三个线程的 ID 分别为 A、B、C,每一个线程将本身的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示框架

public class TestABCAlternate {

public static void main(String[] args) {
	AlternateDemo ad = new AlternateDemo();
	
	new Thread(new Runnable() {
		@Override
		public void run() {
			
			for (int i = 1; i <= 20; i++) {
				ad.loopA(i);
			}
			
		}
	}, "A").start();
	
	new Thread(new Runnable() {
		@Override
		public void run() {
			
			for (int i = 1; i <= 20; i++) {
				ad.loopB(i);
			}
			
		}
	}, "B").start();
	
	new Thread(new Runnable() {
		@Override
		public void run() {
			
			for (int i = 1; i <= 20; i++) {
				ad.loopC(i);
				
				System.out.println("-----------------------------------");
			}
			
		}
	}, "C").start();
	}

}

class AlternateDemo{

	private int number = 1; //当前正在执行线程的标记
	
	private Lock lock = new ReentrantLock();
	private Condition condition1 = lock.newCondition();
	private Condition condition2 = lock.newCondition();
	private Condition condition3 = lock.newCondition();
	
	/**
	 * @param totalLoop : 循环第几轮
	 */
	public void loopA(int totalLoop){
		lock.lock();
		
		try {
			//1. 判断
			if(number != 1){
				condition1.await();
			}
			
			//2. 打印
			for (int i = 1; i <= 1; i++) {
				System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop);
			}
			
			//3. 唤醒
			number = 2;
			condition2.signal();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	public void loopB(int totalLoop){
		lock.lock();
		
		try {
			//1. 判断
			if(number != 2){
				condition2.await();
			}
			
			//2. 打印
			for (int i = 1; i <= 1; i++) {
				System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop);
			}
			
			//3. 唤醒
			number = 3;
			condition3.signal();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	public void loopC(int totalLoop){
		lock.lock();
		
		try {
			//1. 判断
			if(number != 3){
				condition3.await();
			}
			
			//2. 打印
			for (int i = 1; i <= 1; i++) {
				System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop);
			}
			
			//3. 唤醒
			number = 1;
			condition1.signal();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
			}
		}
	}

##10.ReadWirteLock读写锁 ReadWriteLock维护了一对相关的锁,一个用于只读操做,另外一个用于写入操做。只要没有Writer,读取锁能够由多个reader线程同时保持。写入锁是独占的。<br> ReadWriteLock 读取操做一般不会改变共享资源,但执行写入操做时,必须独占方式来获取锁。ide

##11.线程池 第四种获取线程的方法: 线程池,一个ExecutorService,它使用可能的几个线程池之一执行每一个提交的任务,一般使用Executors工厂方法配置。<br/> 1、线程池:提供了一个线程队列,队列中保存着全部等待状态的线程。避免了建立与销毁额外开销,提升了响应的速度。<br> 2、线程池的体系结构:<br> java.util.concurrent.Executor : 负责线程的使用与调度的根接口<br> |--ExecutorService 子接口: 线程池的主要接口<br> |--ThreadPoolExecutor 线程池的实现类<br> |--ScheduledExecutorService 子接口:负责线程的调度<br> |--ScheduledThreadPoolExecutor :继承 ThreadPoolExecutor, 实现 ScheduledExecutorService<br> 3、工具类 : Executors <br> ExecutorService newFixedThreadPool() : 建立固定大小的线程池<br> ExecutorService newCachedThreadPool() : 缓存线程池,线程池的数量不固定,能够根据需求自动的更改数<br> ExecutorService newSingleThreadExecutor() : 建立单个线程池。线程池中只有一个线程<br> ScheduledExecutorService newScheduledThreadPool() : 建立固定大小的线程,能够延迟或定时的执行任务。 ##12.线程调度 一个ScheduledExecutorService,可安排在给定的延迟后运行或按期地执行命令。 ##13.ForkJoinPool 分支/合并框架 工做窃取 Fork/Join框架:就是在必要的状况下,将一个大任务,进行拆分红若干个小任务(拆到不可再拆时),再将一个个的小人物运算的结果进行join汇总。<br>工具

工做窃取 : 当执行新的任务时它能够将其拆分分红更小的任务执行,并将小任务加到线程队列中,而后再从一个随机线程的队列中偷一个并把它放在本身的队列中,而后再从一个随机线程的队列中偷一个并把它放在本身的队列中。

原文出处:https://www.cnblogs.com/liben123/p/11082263.html

相关文章
相关标签/搜索