zoukankan      html  css  js  c++  java
  • java 并发原子性与易变性 来自thinking in java4 21.3.3

    java 并发原子性与易变性  具体介绍请參阅thinking in java4 21.3.3

    thinking in java 4免费下载:http://download.csdn.net/detail/liangrui1988/7580155

    package org.rui.thread.volatiles;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    /**
     * 假设你盲目地应用原子性慨念。那么就会看到在以下程序中的getValue符合上面的描写叙述
     * 
     * 可是,该程序将找到奇数值并终止。虽然return i确实是原子性操作。可是缺少同步使得其数值能够在处于不稳定的中间状态时被读取。
     * 除此之外,因为i也不是volatile的,因此还存在可视性问题
     * @author lenovo
     *
     */
    public class AtomicityTest implements Runnable {
    
    	private int i=0;
    	public int getValue(){return i;}
    	private synchronized void evenIncrement(){i++;i++;}
    	@Override
    	public void run() {
    		while(true)
    			evenIncrement();
    		
    	}
    	
    	public static void main(String[] args) {
    		ExecutorService exec=Executors.newCachedThreadPool();
    		AtomicityTest at=new AtomicityTest();
    		exec.execute(at);
    		while(true)
    		{
    			int val=at.getValue();
    			if(val%2!=0)
    			{
    				System.out.println(val);
    				System.exit(0);
    			}
    		}
    	}
    
    }
    

    package org.rui.thread.volatiles;
    /**
     * 考虑一些更简单的事情。一个产生序列数字的类,
     * 每当nextSerial-Number被调用时,它必须向调用者返回唯一的值
     * @author lenovo
     *
     */
    public class SerialNumberGenerator {
    
    	private static volatile int serialNumber=0;
    	public static int nextSerialNumber()
    	{
    		return serialNumber++;//非线程安全
    	}
    }
    

    package org.rui.thread.volatiles;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    /**
     * 为了測试SerialNumberGenerator 我们须要不会耗尽内存的集(SET) 。
     * 以防须要花费非常长的时间来探測问题。

    这里所看到的的circularSet重用了存储int数值的内存, * 并假设在你生成序列数时,产生数值覆盖冲突的可能性极小。add 和contains 方法都 是synchronized,以防示线程冲突 * @author lenovo * */ //重用存储所以我们不耗尽内存 //reuses storage so we don't run out of memory class CircularSet { private int[] array; private int len; private int index=0; public CircularSet(int size){ array=new int[size]; len=size; //初始化一个值而不是生产 //这个初始全是-1和serialNumberGenerator 不同样。其后取serialNumberGenerator.next...存入 //by the serialNumberGenerator; for(int i=0;i<size;i++) array[i]=-1; } //add public synchronized void add(int i) { array[index]=i; //wrap index and write over old elements; 将指数和写在旧元素; index=++index % len; //System.out.println(index+" : len :"+len); } //contains public synchronized boolean contains(int val) { for(int i=0;i<len;i++) { System.out.println(array[i]+" == "+val); if(array[i]==val) return true; } return false; } } /////////////////////////////////////////////// public class SerialNumberChecker { private static final int SIZE=10; private static CircularSet serials=new CircularSet(1000); private static ExecutorService exec=Executors.newCachedThreadPool(); static class SerialChecker implements Runnable { @Override public void run() { while(true) { //自增长 int serial=SerialNumberGenerator.nextSerialNumber(); if(serials.contains(serial)) { //反复 System.out.println("Duplicate: "+serial); System.exit(0); } serials.add(serial); } } } //// public static void main(String[] args) throws NumberFormatException, InterruptedException { String[] arg=new String[]{"10000"}; for(int i=0;i<SIZE;i++) { exec.execute(new SerialChecker()); //stop after n seconds if there 's an argument 停止在n秒后假设有一个论点 if(arg.length>0) { TimeUnit.SECONDS.sleep(new Integer(arg[0])); System.out.println("没有反复检測"); System.exit(0); } } } } /** * 通过创建多个任务来竞争序列数,你将发现这些任务终于会得到反复的序列数,假设你执行的时间足够长的话 * 为了解决问题,nextSerialNumber 前面加入 了synchronized关健字 */



  • 相关阅读:
    线程池优化之充分利用线程池资源
    Spring异步调用原理及SpringAop拦截器链原理
    使用pdfBox实现pdf转图片,解决中文方块乱码等问题
    Spring BPP中优雅的创建动态代理Bean
    转载:ThreadPoolExecutor 源码阅读
    Springboot定时任务原理及如何动态创建定时任务
    SpringSecurity整合JWT
    SpringMvc接口中转设计(策略+模板方法)
    HashMap 源码阅读
    支付宝敏感信息解密
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/6977746.html
Copyright © 2011-2022 走看看