我知道有一种方法可以在Java中同步变量。那就是使用锁。
public class MsLunch {
private ArrayList<ClientHandler> clients = new ArrayList<ClientHandler>();
private Object lock1 = new Object();
public void inc1() {
synchronized(lock1) {
//maybe add something into the array list
}
}
}
我很好奇我们是否可以按照以下方式进行操作?如果是,任何参考?
public class MsLunch {
private ArrayList<ClientHandler> clients = new ArrayList<ClientHandler>();
public void inc1() {
synchronized (clients) {
//maybe add something into the array list
}
}
}
答案 0 :(得分:0)
如果使用clients
同步代码块,则没有问题。您可以使用任何对象引用来同步代码块。只需确保不会在多个线程的同一实例中重新初始化此对象。
如果你需要一个可以通过线程访问的容器,我建议先查看Queue
和Map
,因为通常他们可以解决很多用例。如果您只需要List
,我建议使用Collections#synchronized(yourList)
,并作为最后一个资源CopyOnWriteArrayList
。尽管如此,这些方法中的任何一种都比自己同步这些资源更好。
答案 1 :(得分:0)
是的,你可以,但你不应该......
Java在java.util.concurrent
package中使用并发List实用程序。使用CopyOnWriteArrayList
而不是使用synchronize
关键字性能更好地使用并发实用程序。这将使您免于处理锁的麻烦
在你的代码中。
答案 2 :(得分:0)
我对我们是否可以按照以下方式进行操作感到好奇?
是的,你可以。
如果是,可以参考吗?
您可以在任何Object
上执行同步。因为ArrayList
是Object
,所以你可以这样做。
你应该将clients
声明为final
变量,因为不同的线程可能会锁定不同的对象,即使在同一个对象上运行也是如此。
此外,您可以使用java.util.concurrent.locks.Lock
和/或java.util.concurrent.locks.ReadWriteLock
代替synchronized
阻止,或只使用符合您需求的java.util.concurrent.CopyOnWriteArrayList
。
我做了一个简单的性能测试:
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ConcurrentReadWriteListTest {
public static void main(String[] args) throws InterruptedException {
final int iterations = 10;
final long durationMillis = 5000;
System.out.println("WarmUp :");
System.out.println("\n************* SynchronizedArrayList ************");
testSynchronizedArrayList(5, 1000);
System.out.println("\n************* CopyOnWriteArrayList *************");
testCopyOnWriteArrayList(5, 1000);
System.out.println("\n********** ArrayListWithReadWriteLock **********");
testArrayListWithReadWriteLock(5, 1000);
System.out.println("\n\nStart Test :");
System.out.println("\n************* SynchronizedArrayList ************");
testSynchronizedArrayList(iterations, durationMillis);
System.out.println("\n************* CopyOnWriteArrayList *************");
testCopyOnWriteArrayList(iterations, durationMillis);
System.out.println("\n********** ArrayListWithReadWriteLock **********");
testArrayListWithReadWriteLock(iterations, durationMillis);
}
static void testSynchronizedArrayList(int iterations, long durationMillis) {
final List<TestObject> list = Collections.synchronizedList(new ArrayList<>());
final AtomicInteger writes = new AtomicInteger();
final AtomicInteger reads = new AtomicInteger();
final Runnable w = () -> {
while (notInterrupted()) {
list.add(new TestObject());
writes.getAndIncrement();
}
};
final Runnable r = () -> {
while (notInterrupted()) {
if (!list.isEmpty()) {
list.get(ThreadLocalRandom.current().nextInt(list.size())).map.size();
reads.getAndIncrement();
}
}
};
beginTest(iterations, durationMillis, list, writes, reads, w, r);
}
static void testCopyOnWriteArrayList(int iterations, long durationMillis) {
final List<TestObject> list = new CopyOnWriteArrayList<>();
final AtomicInteger writes = new AtomicInteger();
final AtomicInteger reads = new AtomicInteger();
final Runnable w = () -> {
while (notInterrupted()) {
list.add(new TestObject());
writes.getAndIncrement();
}
};
final Runnable r = () -> {
while (notInterrupted()) {
if (!list.isEmpty()) {
list.get(ThreadLocalRandom.current().nextInt(list.size())).map.size();
reads.getAndIncrement();
}
}
};
beginTest(iterations, durationMillis, list, writes, reads, w, r);
}
static void testArrayListWithReadWriteLock(int iterations, long durationMillis) {
final List<TestObject> list = new ArrayList<>();
final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
final AtomicInteger writes = new AtomicInteger();
final AtomicInteger reads = new AtomicInteger();
final Runnable w = () -> {
while (notInterrupted()) {
readWriteLock.writeLock().lock();
list.add(new TestObject());
readWriteLock.writeLock().unlock();
writes.getAndIncrement();
}
};
final Runnable r = () -> {
while (notInterrupted()) {
readWriteLock.readLock().lock();
if (!list.isEmpty()) {
list.get(ThreadLocalRandom.current().nextInt(list.size())).map.size();
reads.getAndIncrement();
}
readWriteLock.readLock().unlock();
}
};
beginTest(iterations, durationMillis, list, writes, reads, w, r);
}
static void beginTest(int iterations, long durationMillis,
List<TestObject> list,
AtomicInteger writes, AtomicInteger reads,
Runnable w, Runnable r) {
double totalWPS = 0, totalRPS = 0;
for (int i = 0; i < iterations; i++) {
Thread writer = new Thread(w);
Thread reader = new Thread(r);
writer.start();
reader.start();
sleep(durationMillis);
writer.interrupt();
reader.interrupt();
double wps = writes.get() * 1.0 / durationMillis * 1000;
double rps = reads.get() * 1.0 / durationMillis * 1000;
totalWPS += wps;
totalRPS += rps;
System.out.printf("round(%d) : %.2f w/s, %.2f r/s%n", i + 1, wps, rps);
list.clear();
writes.set(0);
reads.set(0);
}
System.out.printf("overall : %.2f w/s, %.2f r/s%n", totalWPS / iterations, totalRPS / iterations);
}
static boolean notInterrupted() {
return !Thread.currentThread().isInterrupted();
}
static void sleep(long timeout) {
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static final class TestObject {
int i;
long l;
float f;
double d;
Map<Long, String> map = new HashMap<>();
TestObject() {
map.put(1L, "a");
map.put(2L, "b");
map.put(3L, "c");
map.put(4L, "d");
}
}
}
结果如下:
WarmUp :
************* SynchronizedArrayList ************
round(1) : 417859.00 w/s, 361950.00 r/s
round(2) : 845857.00 w/s, 796326.00 r/s
round(3) : 1444301.00 w/s, 1731925.00 r/s
round(4) : 1170101.00 w/s, 954809.00 r/s
round(5) : 1373893.00 w/s, 1343517.00 r/s
overall : 1050402.20 w/s, 1037705.40 r/s
************* CopyOnWriteArrayList *************
round(1) : 52490.00 w/s, 12505323.00 r/s
round(2) : 54170.00 w/s, 12963819.00 r/s
round(3) : 55552.00 w/s, 12723022.00 r/s
round(4) : 56634.00 w/s, 12963812.00 r/s
round(5) : 57261.00 w/s, 12859154.00 r/s
overall : 55221.40 w/s, 12803026.00 r/s
********** ArrayListWithReadWriteLock **********
round(1) : 1526100.00 w/s, 47806.00 r/s
round(2) : 2028127.00 w/s, 97690.00 r/s
round(3) : 2277951.00 w/s, 129597.00 r/s
round(4) : 2065762.00 w/s, 178288.00 r/s
round(5) : 1815661.00 w/s, 200642.00 r/s
overall : 1942720.20 w/s, 130804.60 r/s
Start Test :
************* SynchronizedArrayList ************
round(1) : 766045.40 w/s, 670402.20 r/s
round(2) : 943151.00 w/s, 596922.60 r/s
round(3) : 799154.60 w/s, 603495.60 r/s
round(4) : 799162.40 w/s, 633526.40 r/s
round(5) : 799159.80 w/s, 595249.40 r/s
round(6) : 798720.00 w/s, 526994.40 r/s
round(7) : 959635.00 w/s, 692030.20 r/s
round(8) : 959631.60 w/s, 651675.00 r/s
round(9) : 959632.40 w/s, 652545.80 r/s
round(10) : 959632.40 w/s, 689399.60 r/s
overall : 874392.46 w/s, 631224.12 r/s
************* CopyOnWriteArrayList *************
round(1) : 23536.60 w/s, 13772252.60 r/s
round(2) : 24099.40 w/s, 13332508.00 r/s
round(3) : 24754.80 w/s, 12908797.20 r/s
round(4) : 24895.80 w/s, 12503731.20 r/s
round(5) : 24799.40 w/s, 12386501.60 r/s
round(6) : 24966.20 w/s, 12297215.40 r/s
round(7) : 24769.00 w/s, 12245010.20 r/s
round(8) : 24958.80 w/s, 12399174.00 r/s
round(9) : 24748.40 w/s, 12353819.80 r/s
round(10) : 24942.80 w/s, 12400986.80 r/s
overall : 24647.12 w/s, 12659999.68 r/s
********** ArrayListWithReadWriteLock **********
round(1) : 816296.80 w/s, 67670.40 r/s
round(2) : 872701.20 w/s, 81845.20 r/s
round(3) : 936945.20 w/s, 72189.40 r/s
round(4) : 936311.00 w/s, 80164.40 r/s
round(5) : 934575.00 w/s, 80447.80 r/s
round(6) : 932832.60 w/s, 95923.00 r/s
round(7) : 935632.20 w/s, 85815.00 r/s
round(8) : 935526.20 w/s, 85754.40 r/s
round(9) : 930819.20 w/s, 92297.60 r/s
round(10) : 934331.20 w/s, 94485.60 r/s
overall : 916597.06 w/s, 83659.28 r/s
所以,如果你想要更多更好的
CopyOnWriteArrayList
ArrayList
与ReadWriteLock
一起使用如果你想要介于两者之间,请使用synchronized
阻止。