在开发过程中 当我们拿到一个线程非安全的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. python 手动拼接json数据

    第一步:分别拼接为字符串 第二步:将字符串转化为list 第三歩:将两个list合并为dict 第四步:将dict转换为接送数据 如:  import json keys = ['a', 'b', ' ...

  2. HDU1176-免费馅饼(DP)

    免费馅饼 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  3. JavaWeb_初识监听器Listener

    监听器(listener):对项目起到监听的作用,它能感知到包括request(请求域),session(会话域)和applicaiton(应用程序)的初始化和属性的变化 监听器是Servlet规范中 ...

  4. JavaWeb_客户端相对/绝对路径和服务器端路径

    客户端的绝对路径和相对路径 相对路径:相对与某个基准目录的路径,在同一根目录下各子目录文件之间的相互引用, 绝对路径:指目录下的绝对位置,直接到的目标位置 @charset "UTF-8&q ...

  5. 客户端框架-MVVM

    MVVM Model-View-ViewModel 如果说MVP是对MVC的进一步改进,那么MVVM则是思想的完全变革.它是将"数据模型数据双向绑定"的思想作为核心,因此在View ...

  6. [CSP-S模拟测试]:笨小猴(随机化)

    题目传送门(内部题118) 输入格式 输入第一行是一个整数$n$,意义如以上所示. 接下来有$2n+1$行,每行为两个正整数,第$i$行的两个正整数分别代表$A_i$和$B_i$. 输出格式 如果无法 ...

  7. Babel编辑ES6代码

    1.安装babel依赖 npm install --save-dev @babel/core @babel/cli @babel/preset-env npm install --save @babe ...

  8. servlet3.0无web.xml

    大家应该都已经知道spring 3.1对无web.xml式基于代码配置的servlet3.0应用.通过spring的api或是网络上高手们的博文,也一定很快就学会并且加到自己的应用中去了.PS:如果还 ...

  9. 只运行一个loop脚本

    #!/bin/bash dir=$(dirname $(readlink -f "$0")) full=$(readlink -f "$0") name=$(b ...

  10. Mybaits 运行原理流程图