保证方法调用链的原子性
如果我们想创建一个对象的实例,而这个对象的实例是通过链式调用创建的。然后我们需要保证链调用的原子性。
请考虑以下示例:
public class ChainedMethod {
private int age=0;
private String name="";
private String adress="";
public ChainedMethod setAdress(String adress) {
this.adress = adress;
return this;
}
public ChainedMethod setAge(int age) {
this.age = age;
return this;
}
public ChainedMethod setName(String name) {
this.name = name;
return this;
}
}
一个非常简单的对象,我们定义了三个属性,每个时间集返回一个对此的引用。
https://club.lenovo.com.cn/thread-6601546-1-1.html
https://club.lenovo.com.cn/thread-6601557-1-1.html
https://club.lenovo.com.cn/thread-6601570-1-1.html
https://club.lenovo.com.cn/thread-6601817-1-1.html
https://club.lenovo.com.cn/thread-6601839-1-1.html
https://club.lenovo.com.cn/thread-6601855-1-1.html
https://club.lenovo.com.cn/thread-6601867-1-1.html
https://club.lenovo.com.cn/thread-6601882-1-1.html
https://club.lenovo.com.cn/thread-6601897-1-1.html
https://club.lenovo.com.cn/thread-6601916-1-1.html
https://club.lenovo.com.cn/thread-6601933-1-1.html
https://club.lenovo.com.cn/thread-6601984-1-1.html
https://club.lenovo.com.cn/thread-6601999-1-1.html
https://club.lenovo.com.cn/thread-6602020-1-1.html
https://club.lenovo.com.cn/thread-6602060-1-1.html
https://club.lenovo.com.cn/thread-6602088-1-1.html
https://club.lenovo.com.cn/thread-6602105-1-1.html
https://club.lenovo.com.cn/thread-6602117-1-1.html
https://club.lenovo.com.cn/thread-6602372-1-1.html
https://club.lenovo.com.cn/thread-6602396-1-1.html
https://club.lenovo.com.cn/thread-6602406-1-1.html
https://club.lenovo.com.cn/thread-6602417-1-1.html
https://club.lenovo.com.cn/thread-6602427-1-1.html
https://club.lenovo.com.cn/thread-6602435-1-1.html
https://club.lenovo.com.cn/thread-6602446-1-1.html
https://club.lenovo.com.cn/thread-6602467-1-1.html
https://club.lenovo.com.cn/thread-6602504-1-1.html
https://club.lenovo.com.cn/thread-6602520-1-1.html
https://club.lenovo.com.cn/thread-6602553-1-1.html
https://club.lenovo.com.cn/thread-6602591-1-1.html
https://club.lenovo.com.cn/thread-6602610-1-1.html
https://club.lenovo.com.cn/thread-6602623-1-1.html
https://club.lenovo.com.cn/thread-6602633-1-1.html
https://club.lenovo.com.cn/thread-6603123-1-1.html
https://club.lenovo.com.cn/thread-6603204-1-1.html
https://club.lenovo.com.cn/thread-6603239-1-1.html
https://club.lenovo.com.cn/thread-6603278-1-1.html
https://club.lenovo.com.cn/thread-6603319-1-1.html
https://club.lenovo.com.cn/thread-6603342-1-1.html
https://club.lenovo.com.cn/thread-6603371-1-1.html
https://club.lenovo.com.cn/thread-6603421-1-1.html
https://club.lenovo.com.cn/thread-6603494-1-1.html
https://club.lenovo.com.cn/thread-6603513-1-1.html
https://club.lenovo.com.cn/thread-6603572-1-1.html
https://club.lenovo.com.cn/thread-6603643-1-1.html
https://club.lenovo.com.cn/thread-6603688-1-1.html
https://club.lenovo.com.cn/thread-6603969-1-1.html
https://club.lenovo.com.cn/thread-6603984-1-1.html
https://club.lenovo.com.cn/thread-6604101-1-1.html
https://club.lenovo.com.cn/thread-6604188-1-1.html
https://club.lenovo.com.cn/thread-6604203-1-1.html
https://club.lenovo.com.cn/thread-6604226-1-1.html
https://club.lenovo.com.cn/thread-6604266-1-1.html
https://club.lenovo.com.cn/thread-6604297-1-1.html
https://club.lenovo.com.cn/thread-6604321-1-1.html
https://club.lenovo.com.cn/thread-6604351-1-1.html
https://club.lenovo.com.cn/thread-6604456-1-1.html
https://club.lenovo.com.cn/thread-6604482-1-1.html
https://club.lenovo.com.cn/thread-6604542-1-1.html
https://club.lenovo.com.cn/thread-6604644-1-1.html
https://club.lenovo.com.cn/thread-6604706-1-1.html
https://club.lenovo.com.cn/thread-6604983-1-1.html
https://club.lenovo.com.cn/thread-6604998-1-1.html
https://club.lenovo.com.cn/thread-6605111-1-1.html
https://club.lenovo.com.cn/thread-6605152-1-1.html
https://club.lenovo.com.cn/thread-6605172-1-1.html
https://club.lenovo.com.cn/thread-6605190-1-1.html
https://club.lenovo.com.cn/thread-6605207-1-1.html
https://club.lenovo.com.cn/thread-6605226-1-1.html
https://club.lenovo.com.cn/thread-6605254-1-1.html
https://club.lenovo.com.cn/thread-6605288-1-1.html
https://club.lenovo.com.cn/thread-6605357-1-1.html
https://club.lenovo.com.cn/thread-6605388-1-1.html
https://club.lenovo.com.cn/thread-6605423-1-1.html
https://club.lenovo.com.cn/thread-6605468-1-1.html
https://club.lenovo.com.cn/thread-6605513-1-1.html
https://club.lenovo.com.cn/thread-6605988-1-1.html
https://club.lenovo.com.cn/thread-6606015-1-1.html
https://club.lenovo.com.cn/thread-6606203-1-1.html
https://club.lenovo.com.cn/thread-6606251-1-1.html
https://club.lenovo.com.cn/thread-6606260-1-1.html
https://club.lenovo.com.cn/thread-6606274-1-1.html
https://club.lenovo.com.cn/thread-6606287-1-1.html
https://club.lenovo.com.cn/thread-6606300-1-1.html
https://club.lenovo.com.cn/thread-6606316-1-1.html
https://club.lenovo.com.cn/thread-6606359-1-1.html
https://club.lenovo.com.cn/thread-6606422-1-1.html
https://club.lenovo.com.cn/thread-6606445-1-1.html
https://club.lenovo.com.cn/thread-6606477-1-1.html
https://club.lenovo.com.cn/thread-6606521-1-1.html
https://club.lenovo.com.cn/thread-6606541-1-1.html
https://club.lenovo.com.cn/thread-6606934-1-1.html
https://club.lenovo.com.cn/thread-6606957-1-1.html
https://club.lenovo.com.cn/thread-6607669-1-1.html
https://club.lenovo.com.cn/thread-6607696-1-1.html
https://club.lenovo.com.cn/thread-6607711-1-1.html
https://club.lenovo.com.cn/thread-6607721-1-1.html
https://club.lenovo.com.cn/thread-6607729-1-1.html
https://club.lenovo.com.cn/thread-6607737-1-1.html
https://club.lenovo.com.cn/thread-6607749-1-1.html
https://club.lenovo.com.cn/thread-6607764-1-1.html
https://club.lenovo.com.cn/thread-6607773-1-1.html
https://club.lenovo.com.cn/thread-6607790-1-1.html
https://club.lenovo.com.cn/thread-6607804-1-1.html
https://club.lenovo.com.cn/thread-6607820-1-1.html
https://club.lenovo.com.cn/thread-6607836-1-1.html
https://club.lenovo.com.cn/thread-6608067-1-1.html
https://club.lenovo.com.cn/thread-6608103-1-1.html
https://mclub.lenovo.com.cn/thread-6592866-1-1.html
https://mclub.lenovo.com.cn/thread-6594212-1-1.html
https://mclub.lenovo.com.cn/thread-6594213-1-1.html
https://mclub.lenovo.com.cn/thread-6594216-1-1.html
https://mclub.lenovo.com.cn/thread-6594217-1-1.html
https://mclub.lenovo.com.cn/thread-6594220-1-1.html
https://mclub.lenovo.com.cn/thread-6594335-1-1.html
https://mclub.lenovo.com.cn/thread-6594337-1-1.html
https://mclub.lenovo.com.cn/thread-6594342-1-1.html
https://mclub.lenovo.com.cn/thread-6594344-1-1.html
https://mclub.lenovo.com.cn/thread-6594349-1-1.html
https://mclub.lenovo.com.cn/thread-6594353-1-1.html
让我们看看如何在多线程环境中调用:
ChainedMethod chainedMethod= new ChainedMethod();
Thread t1 = new Thread(() -> chainedMethod.setAge(1).setAdress("www").setName("name1"));
t1.start();
Thread t2 = new Thread(() -> chainedMethod.setAge(2).setAdress("www2").setName("name2"));
t2.start();
因为在多线程环境下,上面设置的方法可能会比较混乱。怎么解决?我们可以首先创建一个本地副本,这是线程安全的,因为它是在本地访问的,最后将副本复制到新创建的实例对象。
主要代码如下:
public class ChainedMethodWithBuilder {
private int age=0;
private String name="";
private String adress="";
public ChainedMethodWithBuilder(Builder builder){
this.adress=builder.adress;
this.age=builder.age;
this.name=builder.name;
}
public static class Builder{
private int age=0;
private String name="";
private String adress="";
public static Builder newInstance(){
return new Builder();
}
private Builder() {}
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setAge(int age) {
this.age = age;
return this;
}
public Builder setAdress(String adress) {
this.adress = adress;
return this;
}
public ChainedMethodWithBuilder build(){
return new ChainedMethodWithBuilder(this);
}
}
我们看下怎么调用:
final ChainedMethodWithBuilder[] builder = new ChainedMethodWithBuilder[1];
Thread t1 = new Thread(() -> {
builder[0] =ChainedMethodWithBuilder.Builder.newInstance()
.setAge(1).setAdress("www").setName("name1")
.build();});
t1.start();
Thread t2 = new Thread(() ->{
builder[0] =ChainedMethodWithBuilder.Builder.newInstance()
.setAge(1).setAdress("www").setName("name1")
.build();});
t2.start();
因为lambda表达式中使用的变量必须是最终的或最终等价的,所以我们需要构建一个最终数组。
读写64bits的值
在java中,64位长和double被视为两个32位。
因此,64位的一个操作被分成32位的两个操作。这就导致了原子问题。
请考虑以下代码:
public class LongUsage {
private long i =0;
public void setLong(long i){
this.i=i;
}
public void printLong(){
System.out.println("i="+i);
}
}
因为long的读写分为两部分,如果在多线程环境中多次调用setLong和printLong的方法,可能会出现问题。
解决方法很简单,长变量或双变量都可以定义为volatile。
private volatile long i = 0;