如何在一个线程环境中使用一个线程非安全的java类

 在开发过程中 当我们拿到一个线程非安全的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]
--------------------
原文地址:https://www.cnblogs.com/ChenD/p/7890229.html