Я просматривал книгу Java Параллелизм на практике . Там они заявляют, что объекты без сохранения состояния всегда являются потокобезопасными.
import java.math.BigInteger;
import javax.servlet.*;
import net.jcip.annotations.*;
/**
* StatelessFactorizer
*
* A stateless servlet
*
* @author Brian Goetz and Tim Peierls
*/
@ThreadSafe
public class StatelessFactorizer extends GenericServlet implements Servlet {
public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = factor(i);
encodeIntoResponse(resp, factors);
}
void encodeIntoResponse(ServletResponse resp, BigInteger[] factors) {
}
BigInteger extractFromRequest(ServletRequest req) {
return new BigInteger("7");
}
BigInteger[] factor(BigInteger i) {
// Doesn't really factor
return new BigInteger[] { i };
}
}
Через несколько дней, когда я добрался до главы 3, я прочитал о безопасной публикации в главе 3. Прочитав листинг 3.9 этого раздела, я запутался. действительно ли StatelessFactorizer
потокобезопасен, поскольку мы разрешаем выход из массива BigInteger и одного объекта BigInteger, присутствующего в методе service .
Также, когда я могу сказать, что его безопасно даже после публикации другим методом?
Для справки прикрепите код Листинга 3.9
package net.jcip.examples;
import java.util.*;
/**
* Animals
* <p/>
* Thread confinement of local primitive and reference variables
*
* @author Brian Goetz and Tim Peierls
*/
public class Animals {
Ark ark;
Species species;
Gender gender;
public int loadTheArk(Collection<Animal> candidates) {
SortedSet<Animal> animals;
int numPairs = 0;
Animal candidate = null;
// animals confined to method, don't let them escape!
animals = new TreeSet<Animal>(new SpeciesGenderComparator());
animals.addAll(candidates);
for (Animal a : animals) {
if (candidate == null || !candidate.isPotentialMate(a))
candidate = a;
else {
ark.load(new AnimalPair(candidate, a));
++numPairs;
candidate = null;
}
}
return numPairs;
}
class Animal {
Species species;
Gender gender;
public boolean isPotentialMate(Animal other) {
return species == other.species && gender != other.gender;
}
}
enum Species {
AARDVARK, BENGAL_TIGER, CARIBOU, DINGO, ELEPHANT, FROG, GNU, HYENA,
IGUANA, JAGUAR, KIWI, LEOPARD, MASTADON, NEWT, OCTOPUS,
PIRANHA, QUETZAL, RHINOCEROS, SALAMANDER, THREE_TOED_SLOTH,
UNICORN, VIPER, WEREWOLF, XANTHUS_HUMMINBIRD, YAK, ZEBRA
}
enum Gender {
MALE, FEMALE
}
class AnimalPair {
private final Animal one, two;
public AnimalPair(Animal one, Animal two) {
this.one = one;
this.two = two;
}
}
class SpeciesGenderComparator implements Comparator<Animal> {
public int compare(Animal one, Animal two) {
int speciesCompare = one.species.compareTo(two.species);
return (speciesCompare != 0)
? speciesCompare
: one.gender.compareTo(two.gender);
}
}
class Ark {
private final Set<AnimalPair> loadedAnimals = new HashSet<AnimalPair>();
public void load(AnimalPair pair) {
loadedAnimals.add(pair);
}
}
}