Здравствуйте, andyag, Вы писали:
a> А не встречал ли кто библиотеку, реализующую коллекции с поддержкой транзакций? Причём не обязательно даже чтобы поддержка concurrency была. Хочется примерно вот такого:
Можно взять стек неизменяемых списков
import org.pcollections.PVector;
import org.pcollections.TreePVector;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
public class TransactionalList<E>
{
final Deque<PVector<E>> data = new ArrayDeque<>();
public TransactionalList()
{
data.addFirst(TreePVector.<E>empty());
}
public void add(E e)
{
data.addFirst(data.removeFirst().plus(e));
}
public void begin()
{
data.addFirst(data.getFirst());
}
public void rollback()
{
data.removeFirst();
}
public void commit()
{
final PVector<E> newHead = data.removeFirst();
data.removeFirst();//old head dropped
data.addFirst(newHead);
}
public int size()
{
return data.getFirst().size();
}
public List<? extends E> data()
{
return data.getFirst();
}
}
ну и юнит-тест
import org.junit.Test;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
public class TransactionalListTest
{
@Test
public void testAdd() throws Exception
{
TransactionalList<Integer> list = new TransactionalList<Integer>();
list.begin(); // []
list.begin(); // []
list.add(1); // [1]
assertEquals(1, list.size());
assertEquals(asList(1), list.data());
list.commit(); // [1]
list.begin(); // [1]
list.add(2); // [1, 2]
assertEquals(asList(1, 2), list.data());
assertEquals(2, list.size());
list.commit(); // [1, 2]
list.rollback(); // []
assertEquals(0, list.size());
}
}
С concurrency непонятно что делать. Ведь begin-commit из разных потоков пускать не получится. По-моему можно сделать только саму модификацию списка, через CAS делать замену вершины стека.