在开发过程中 当我们拿到一个线程非安全的java类的时候,我们可以额外创建这个类的管理类 并在管理类中控制同步
比如
一个非线程安全的Pair类
package test.thread.sx.testKuai; /** * 线程非安全的java类 * 约束条件 两个变量的值必须一致 * @author Administrator * */ public class Pair { private int x,y; public Pair(int x,int y){ this.x = x; this.y = y; } public Pair(){ this(0,0); } public int getX() { return x; } public int getY() { return y; } public void incrementX(){ x++; } public void incrementY(){ y++; } @Override public String toString() { return "Pair [x=" + x + ", y=" + y + "]"; } public class PairValuesNotEqualException extends RuntimeException { private static final long serialVersionUID = 673137680063170443L; public PairValuesNotEqualException() { super("Pair value not equal" + Pair.this); } } public void checkState(){ if(x!=y){ throw new PairValuesNotEqualException(); } } }
那么我们想要在线程安全的环境下来操作这个类的话 我们不可以修改原来类的代码结构 我们可以创建一个新的管理类 为了方便我们使用两种方式来实现同步
所以先创建一个abstract的类 然后在创建这个类的实现类
package test.thread.sx.testKuai; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; public abstract class PairManager { protected Pair p = new Pair(); protected List<Pair> storge = Collections.synchronizedList(new ArrayList<Pair>()); /** * 获取pair可以轻松管理同步 * @return */ public synchronized Pair getPair(){ return new Pair(p.getX(), p.getY()); } public abstract void increment(); public void storge(Pair p){ storge.add(p); } }
然后分别创建两个实现类 一个是直接同步方法 一个同步代码块
同步方法
package test.thread.sx.testKuai; public class PairManager1 extends PairManager { @Override public synchronized void increment() { p.incrementX(); p.incrementY(); storge(getPair()); } }
同步代码块
package test.thread.sx.testKuai; public class PairManger2 extends PairManager { @Override public void increment() { Pair temp; synchronized (this) { p.incrementX(); p.incrementY(); temp = getPair(); } storge(temp); } }
其实还可以直接替换 LOCK
package test.thread.sx.testKuai; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class PairManger2 extends PairManager { private Lock lock = new ReentrantLock(); @Override public void increment() { Pair temp; /* synchronized (this) { */ lock.lock(); p.incrementX(); p.incrementY(); temp = getPair(); lock.unlock(); /* } */ storge(temp); } }
在保证线程安全的情况下 为了性能最好是尽量减少同步范围
然后创建线程任务 这个是两个变量同时增加的任务
package test.thread.sx.testKuai; public class PairManipulator implements Runnable { private PairManager pm ; public PairManipulator(PairManager pm) { this.pm = pm; } @Override public void run() { while(true){ pm.increment(); System.out.println(pm.getPair()); } } @Override public String toString() { return "pair:" + pm.getPair() ; } }
然后创建一个检查任务
package test.thread.sx.testKuai; public class PairChecker implements Runnable { private PairManager pm; public PairChecker(PairManager p) { pm = p; } @Override public void run() { while (true) { /* pm.checkCounter.incrementAndGet();*/ pm.getPair().checkState(); System.out.println(pm.getPair()); } } }
然后进行测试
package test.thread.sx.testKuai; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class CiiticalSection { public static void testApproaches(PairManager pmn1,PairManager pmn2){ ExecutorService exc = Executors.newCachedThreadPool(); PairManipulator pm = new PairManipulator(pmn1); PairManipulator pm2 = new PairManipulator(pmn2); PairChecker pc = new PairChecker(pmn1); PairChecker pc2 = new PairChecker(pmn2); exc.execute(pm); exc.execute(pm2); exc.execute(pc); exc.execute(pc2);
exc.shutdown(); } public static void main(String[] args) { PairManager pmn1 = new PairManager1(); PairManager pmn2 = new PairManger2(); testApproaches(pmn1,pmn2); } }
看下结果
----------------- Pair [x=159948, y=159948] Pair [x=159949, y=159949] Pair [x=159950, y=159950] --------------------