zoukankan      html  css  js  c++  java
  • 如何在一个线程环境中使用一个线程非安全的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]
    --------------------
  • 相关阅读:
    Java的代码风格
    哪些你容易忽略的C语言基础知识
    Java基础学习笔记第二章
    Java代码性能优化总结
    Java并发编程(2):线程中断(含代码)
    C语言代码训练(一)
    数控G代码编程详解大全
    PLC编程算法
    博客转移到新地址
    一些吐槽
  • 原文地址:https://www.cnblogs.com/ChenD/p/7890229.html
Copyright © 2011-2022 走看看