在开发过程中 当我们拿到一个线程非安全的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类的更多相关文章

  1. 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法

    [源码下载] 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法 作者:webabcd 介绍重新想象 Wi ...

  2. 分别应用include指令和include动作标识在一个jsp页面中包含一个文件。

    分别应用include指令和include动作标识在一个jsp页面中包含一个文件. hello.jsp <%@ page language="java" import=&qu ...

  3. Confluence 6 从生产环境中恢复一个测试实例

    请参考 Restoring a Test Instance from Production 页面中的内容获得更多完整的说明. 很多 Confluence 的管理员将会使用生产实例运行完整数据和服务的 ...

  4. JDK中的SimpleDateFormat线程非安全

    在JDK中使用SimpleDateFormat的时候都会遇到线程安全的问题,在JDK文档中也说明了该类是线程非安全的,建议对于每个线程都创建一个SimpleDateFormat对象.如下面一个Case ...

  5. 它可以作为一个代理server或者转发java类

    在项目中使用,这简化和通用汽车.突出的基本思路,细节可以基于此类改变. 基于java容器和servlet. package com.xxx.first; import java.io.Buffered ...

  6. 一接口自动化中生成测试数据需要用到的java类API--import java.util.Properties;

    转载地址:    http://www.cnblogs.com/lay2017/p/8596871.html#undefined 写的很详细

  7. 【多线程补充】SimpleDateFormat非线程安全与线程中、线程组中异常的处理

    1.SimpleDateFormat非线程安全的问题 类SimpleDateFormat主要负责日期的转换与格式化,但在多线程环境中,使用此类容易造成数据转换及处理的不正确,因为SimpleDateF ...

  8. 在多线程环境中使用Jedis

    Jedis是一个Java语言的Redis客户端,它为Java语言连接与操作Redis提供了简单易用的接口. Jedis不是线程安全的.故不应该在多线程环境中共用一个Jedis实例.可是.也应该避免直接 ...

  9. OpenStack环境中的NFV实践

    原文链接:http://www.99cloud.net/html/2016/jiuzhouyuanchuang_1103/250.html 在开始实践之前我们首先需要了解一些NFV概念和术语. NFV ...

随机推荐

  1. NOI数论姿势瞎总结(Pi也没有)

    Miller-Rabin素数检测 费马小定理:没人不会吧. 二次探测:如果\(n\)是质数,\(x^2 \equiv 1\ (\mod n)\)的解只有\(x \equiv 1\)或\(x \equi ...

  2. [BZOJ3611][Heoi2014]大工程(虚树上DP)

    3611: [Heoi2014]大工程 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 2464  Solved: 1104[Submit][Statu ...

  3. Set的遍历以及排序详讲

    java中Set集合是一个不包含重复元素的Collection,首先我们先看看遍历方法 package com.sort;   import java.util.HashSet; import jav ...

  4. 暂时跳过的Leetcode题目

    963 最小面积矩形 II 有数学几何的味道,感觉这不是笔试面试的重点. 932 漂亮数组 构造题

  5. springboot 测试发送邮件

    首先在pom文件引入依赖: <!--email依赖 --> <dependency> <groupId>org.springframework.boot</g ...

  6. C++入门经典-例4.9-输出不同生命周期的变量值

    1:代码如下: // 4.9.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> using ...

  7. springboot的优点

    2013年12月12日,spring发布了4.0版本.这个本来只是作为Java平台上的控制反转容器的库,经过将近10年的发展已经成为了一个巨无霸产品.不过其依靠良好的分层设计,每个功能模块都能保持较好 ...

  8. hdjs---1、hdjs爬坑杂记

    hdjs---1.hdjs爬坑杂记 一.总结 一句话总结: 对hdjs这种文档和完善都不是很好的插件,应该先在项目的空页面试,成功后再用到用了框架的项目中 1.hdjs4.0.18引入select2? ...

  9. project2016安装与破解

      分步阅读 project2016发布增加了许多功能.Microsoft Office 2016 官方正式版发布!这是微软发布的全新办公软件套件,相比现有Office 2013的变化也不是很大,界面 ...

  10. redis high available solution/ redis 高可用方案

    http://developers.linecorp.com/blog/?p=1420 http://engineering.docusign.com/articles/redis-sentinel- ...