>

Python之差没有多少总括器

- 编辑:金沙国际平台登录 -

Python之差没有多少总括器

  思路:学会使用正则表明式把须求先实行总括的合营出来,然后再一步步的去算,把先算出来的值替换原来的值,再进一步的把++,--等号成为大家如常的数学上的暗记,然后再拓宽一步步的更迭,最后把带括号的都计算出来,再调用一回加减函数举行计算

import redef atom_cal:      #计算乘除法    if "*" in exp:        a,b = exp.split("*")    #以*作切割,把切出来的两个值分别赋给a,b        return str * float #用float计算ab相乘的值并转换成字符串格式,便于计算    else:        a,b = exp.split("/")    #以/作切割,把切出来的两个值分别赋给a,b        return str / floatdef mul_div:   #乘除    while 1:        ret = re.search("d+?[*/]-?d+?",exp)     #把乘除法匹配出来        if ret:            atom_exp = ret.group()  #取第一个组匹配出来的乘除法            res = atom_cal    #调用atom_cal函数计算乘除法            exp = exp.replace(atom_exp,res)     #替换  将计算出来的值与原式子替换        else:return exp     #当没有相匹配的乘除法时,返回expdef format_exp:    #改变符号    exp = exp.replace("--","+")    exp = exp.replace("-+","-")    exp = exp.replace("+-","-")    exp = exp.replace("++","+")    return expdef add_sub:   #计算加减    ret = re.findall("[+-]?d+?",exp)  #把能加减的匹配出来,包括小数,负数等    exp_sum = 0    for i in ret:        exp_sum += float     #累加至exp_sum中返回    return exp_sumdef cal:    exp = mul_div  #乘除    exp = format_exp #变号    exp_sum = add_sub  #加减    return exp_sum      #floatdef main:    exp = exp.replace(" ","")#去空格    while 1:        ret = re.search("",exp)    #括号最里面的数        if ret:            inner_bracket = ret.group()     #取正则表达式匹配到的第一个组数            res = str(cal(inner_bracket))       #调用cal计算            exp = exp.replace(inner_bracket,res)           #把算出来的值返回给括号            exp = format_exp   #调用函数,变号        else:break    return cals = '1 - 2 * ( (60-30 + * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - / 'print

并发类容器

容器中的十分

Vector是贰个线程安全的器皿,但是下边包车型大巴代码恐怕抛出ArrayIndexOutOfBoundsException

for(int i=0;i<vector.size();i++)
    doSomething(vector.get(i));

在使用迭代器Vector时或然现身CocurrentModificationException

List<String> list = Collections.synchronizedList(new ArrayList<String>);
for(String str: list)
    doSomething(str);

出现下面的主题材料根本归因于这种基于先查看再拜见的点子并非原子的,在那四个步骤中间或许有其余线程修改了容器的高低(比方直接将容器清空),消除的方案正是通过锁机制来有限帮助该操作。

掩盖的迭代器

并发的标题最轻易出现在对容器实行迭代的时候,一相当大心就入坑了。突显的迭代幸好,对于那个隐式的迭代可要小心啊。

private final Set<Integer> set = new HashSet<Integer>();
System.out.println(set);

下边包车型客车代码是打字与印刷出容器的开始和结果,上边的代码中隐式的对set举办了迭代,通过调用容器中各样成分的toString()方法来收获字符串,然后将其拼接起来再出口。
隐式迭代还有containsAll, removeAll和retainAll等情势,还应该有便是将容器作为参数的构造函数也会对容器举办迭代

并发类容器

ConcurrentMap, ConcurrentLinkedQueue, CopyOnWriteArrayList,BlockingQueue等

ConcurrentHashMap的实现

为了增长并发度,选拔锁分离才干来落到实处。内部有四个Segment,三个Segemnt其实就是叁个近乎HashTable的协会。ConcurrentHashMap定位八个因素的进度必要开展三回Hash操作,第一回Hash定位到Segment,第三次Hash定位到成分所在的链表的底部。Segment的个数在Map初步化时就规定了,以往都不会时有产生转移。
get操作没有要求加锁,可是put操作供给加锁

static final class Segment<K,V> extends ReentrantLock implements Serializable {
    transient volatile int count;
    transient int modCount;
    transient int threshold;
    transient volatile HashEntry<K,V>[] table;//注意这句话
    final float loadFactor;
}



在ConcurrentHashMap中对于这一个先反省后拜谒的操作(若未有则增加,若相等则移除,若相等则替换)都改为了原子操作

//当且仅当K没有相应的映射值时才插入
V putIfAbsent(K key, V value)

//当且仅当K被映射到V时才移除
boolean remove(K key, V value)

//当且仅当K被映射到某个值时才替换为newValue
V replace(K key, V newValue)

可伸缩性的结果缓存

在一个业务流程中有一对是耗费时间总结,为了收缩那有的时间,能够将计算结果保存下来。在前日遇到同样的总括时,可以一向从缓存中收取结果,那样就将三个属性瓶颈转为一个可伸缩性瓶颈

public class Memory1 {
    private final Map<String, BigInteger> cache = new HashMap<>();

    public synchronized BigInteger compute(String arg) {
        BigInteger result = cache.get(arg);

        //缓存中没有则计算
        if (result == null) {
            result = compute1(arg);
            cache.put(arg, result);     
        }
        return result;
    }

    public static BigInteger compute1(String arg) {
        //TODO
    }
}

地方的代码是率先版,大家对compute做了加锁操作,不过多少难点。举个例子有四个线程都要计算,而缓存中都从未有过他们的乘除结果且那四个线程的一个钱打二拾七个结结果也不等同。那时只可以等率先个线程先总括甘休,第贰个线程才具计算,那致使运算品质极度差。

public class Memory2 {
    private final Map<String, BigInteger> cache = new ConcurrentHashMap<>();

    public  BigInteger compute(String arg) {
        BigInteger result = cache.get(arg);

        //缓存中没有则计算
        if (result == null) {
            result = compute1(arg);
            cache.put(arg, result);     
        }
        return result;
    }

    public static BigInteger compute1(String arg) {
        //TODO
    }
}

该代码是第二版,即便减弱了锁的粒度(使用了ConcurrentHashMap),相对于第一版提升了并发度。不过又出现了新的难点---当八个线程同时调用compute时大概会招致计算获得一致的值。创新的点子是:叁个将在总结的线程先查看当前正值测算的线程是否和友好算的同样,假诺算的同样则等到其得了,然后去查询缓存中的值。

public class Memory3 {
    private final Map<String, Future<BigInteger>> cache = new ConcurrentHashMap<>();

    public  BigInteger compute(final String arg) {
        Future<BigInteger> result = cache.get(arg);

        //缓存中没有则计算
        if (result == null) {
            Callable<BigInteger> call = new Callable<BigInteger>() {
                public BigInteger = new Callable<BigInteger>() {
                    public BigInteger call() {
                        return compute1(arg);
                    }
                }
            };
            FetureTask<BigInteger> f = new FetureTask<>(call);
            cache.put(arg, f);
            f.run();    
        }
        return f.get(); //将会一直阻塞,直到运算结束
    }

    public static BigInteger compute1(String arg) {
        //TODO
    }
}

该代码是第三版,其行使了FutureTask的特色,当一个线程要获取另三个线程的乘除结果时将会阻塞在get方法上。若结果已经被算出来(保存在Future中),那么将立即赶回。倘诺别的线程正在测算该结果,那么新到的线程将从来等候这几个结果被即使出来。上面的代码照旧有一点点小劣点,因为其有一种恐怕就是同叁个key被put了频仍。

public class Memory3 {
    private final Map<String, Future<BigInteger>> cache = new ConcurrentHashMap<>();

    public  BigInteger compute(final String arg) {
        Future<BigInteger> result = cache.get(arg);

        //缓存中没有则计算
        if (result == null) {
            Callable<BigInteger> call = new Callable<BigInteger>() {
                public BigInteger = new Callable<BigInteger>() {
                    public BigInteger call() {
                        return compute1(arg);
                    }
                }
            };
            FetureTask<BigInteger> f = new FetureTask<>(call);
            result = cache.putIfAbsent(arg, f);
            if (result == null) {
                                    result = f;
                result.run();
                            }
        }

        return result.get(); //将会一直阻塞,直到运算结束
    }

    public static BigInteger compute1(String arg) {
        //TODO
    }
}

上边的代码中,大家采取了putIfAbsent接口,它使得这种先检查后拜访产生了原子性操作

本文由编程发布,转载请注明来源:Python之差没有多少总括器