java并发编程实践之共享对象学习笔记

来源:互联网 发布:矩阵相似性度量 编辑:程序博客网 时间:2024/05/21 08:35

这里写图片描述
过期数据
*线程安全的可变整数访问器:

package com.yihong.javaThread;import net.jcip.annotations.*;/* * 线程安全的可变整数访问器 */@ThreadSafepublic class SynchronizedInteger {    @GuardedBy("this") private int value;    public synchronized int get() {        return value;    }    public synchronized void set(int value) {        this.value = value;    }}

锁和可见性
同步对可见性的保证:
这里写图片描述
这里写图片描述
Volatile变量
这里写图片描述
数绵羊例子:
加锁可以保证可见性与原子性;volatile变量只能保证可见性

package com.yihong.javaThread;/* * 数绵羊 * 加锁可以保证可见性与原子性;volatile变量只能保证可见性 */public class CountingSheep {    volatile boolean asleep;    void tryToSleep() {        while (!asleep)            countSomeSheep();    }    void countSomeSheep() {        // One, two, three...    }}

发布和逸出

package com.yihong.javaThread;import java.util.*;/* * 发布对象 */public class Secrets {    public static Set<Secrets> knownSecrets;    public void initialize() {        knownSecrets = new HashSet<Secrets>();    }}

安全构建的实践
不要让this引用在构造期间逸出。
使用工厂方法防止this引用在构造期间逸出:

package com.yihong.javaThread;/* * 使用工厂方法防止this引用在构造期间逸出 */public class SafeListener {    private final EventListener listener;    private SafeListener() {        listener = new EventListener() {            public void onEvent(Event e) {                doSomething(e);            }        };    }    public static SafeListener newInstance(EventSource source) {        SafeListener safe = new SafeListener();        source.registerListener(safe.listener);        return safe;    }    void doSomething(Event e) {    }    interface EventSource {        void registerListener(EventListener e);    }    interface EventListener {        void onEvent(Event e);    }    interface Event {    }}

栈限制
本地的基本类型和引用类型的变量的线程限制:

package com.yihong.javaThread;import java.util.*;/* * 本地的基本类型和引用类型的变量的线程限制 */public class Animals {    Ark ark;    Species species;    Gender gender;    public int loadTheArk(Collection<Animal> candidates) {        SortedSet<Animal> animals;        int numPairs = 0;        Animal candidate = null;        // animals confined to method, don't let them escape!        animals = new TreeSet<Animal>(new SpeciesGenderComparator());        animals.addAll(candidates);        for (Animal a : animals) {            if (candidate == null || !candidate.isPotentialMate(a))                candidate = a;            else {                ark.load(new AnimalPair(candidate, a));                ++numPairs;                candidate = null;            }        }        return numPairs;    }    class Animal {        Species species;        Gender gender;        public boolean isPotentialMate(Animal other) {            return species == other.species && gender != other.gender;        }    }    enum Species {        AARDVARK, BENGAL_TIGER, CARIBOU, DINGO, ELEPHANT, FROG, GNU, HYENA,        IGUANA, JAGUAR, KIWI, LEOPARD, MASTADON, NEWT, OCTOPUS,        PIRANHA, QUETZAL, RHINOCEROS, SALAMANDER, THREE_TOED_SLOTH,        UNICORN, VIPER, WEREWOLF, XANTHUS_HUMMINBIRD, YAK, ZEBRA    }    enum Gender {        MALE, FEMALE    }    class AnimalPair {        private final Animal one, two;        public AnimalPair(Animal one, Animal two) {            this.one = one;            this.two = two;        }    }    class SpeciesGenderComparator implements Comparator<Animal> {        public int compare(Animal one, Animal two) {            int speciesCompare = one.species.compareTo(two.species);            return (speciesCompare != 0)                    ? speciesCompare                    : one.gender.compareTo(two.gender);        }    }    class Ark {        private final Set<AnimalPair> loadedAnimals = new HashSet<AnimalPair>();        public void load(AnimalPair pair) {            loadedAnimals.add(pair);        }    }}

ThreadLocal
使用ThreadLocal确保线程封闭性:

package com.yihong.javaThread;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;/* * 使用ThreadLocal确保线程封闭性 */public class ConnectionDispenser {    static String DB_URL = "jdbc:mysql://localhost/mydatabase";    private ThreadLocal<Connection> connectionHolder            = new ThreadLocal<Connection>() {                public Connection initialValue() {                    try {                        return DriverManager.getConnection(DB_URL);                    } catch (SQLException e) {                        throw new RuntimeException("Unable to acquire Connection, e");                    }                };            };    public Connection getConnection() {        return connectionHolder.get();    }}

不可变对象永远是线程安全的。
这里写图片描述
构造于底层可变对象之上的不可变类:

package com.yihong.javaThread;import java.util.*;import net.jcip.annotations.*;/* * 构造于底层可变对象之上的不可变类 */@Immutablepublic class ThreeStooges {    private final Set<String> stooges = new HashSet<String>();    public ThreeStooges() {        stooges.add("Moe");        stooges.add("Larry");        stooges.add("Curly");    }    public boolean isStooge(String name) {        return stooges.contains(name);    }    public String getStoogeNames() {        List<String> stooges = new Vector<String>();        stooges.add("Moe");        stooges.add("Larry");        stooges.add("Curly");        return stooges.toString();    }}

final域
这里写图片描述
使用volatile发布不可变对象
在不可变的容器中缓存数字和它的因数:

package com.yihong.javaThread;import java.math.BigInteger;import java.util.*;import net.jcip.annotations.*;/* * 在不可变的容器中缓存数字和它的因数 */@Immutablepublic class OneValueCache {    private final BigInteger lastNumber;    private final BigInteger[] lastFactors;    public OneValueCache(BigInteger i,                         BigInteger[] factors) {        lastNumber = i;        lastFactors = Arrays.copyOf(factors, factors.length);    }    public BigInteger[] getFactors(BigInteger i) {        if (lastNumber == null || !lastNumber.equals(i))            return null;        else            return Arrays.copyOf(lastFactors, lastFactors.length);    }}

安全发布
使用到不可变容器对象的vlolatile类的引用,缓存最新的结果:

package com.yihong.javaThread;import java.math.BigInteger;import javax.servlet.*;import net.jcip.annotations.*;/* * 使用到不可变容器对象的vlolatile类的引用,缓存最新的结果 */@ThreadSafepublic class VolatileCachedFactorizer extends GenericServlet implements Servlet{    private volatile OneValueCache cache = new OneValueCache(null, null);    public void service(ServletRequest req, ServletResponse resp) {        BigInteger i = extractFromRequest(req);        BigInteger[] factors = cache.getFactors(i);        if (factors == null) {            factors = factor(i);            cache = new OneValueCache(i, factors);        }        encodeIntoResponse(resp, factors);    }    void encodeIntoResponse(ServletResponse resp, BigInteger[] factors) {    }    BigInteger extractFromRequest(ServletRequest req) {        return new BigInteger("7");    }    BigInteger[] factor(BigInteger i) {        // Doesn't really factor        return new BigInteger[]{i};    }}

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

阅读全文
0 0