我做了一点测试,因为我想存储一个多个线程一次使用的数组(或某种列表)。
我的班级:
package main;
import java.util.Timer;
import java.util.TimerTask;
public class Main {
private final static Object lock = new Object();
public static void main(String[] args) {
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
synchronized (lock) {
Values.incrementValues();
}
}
}, 1000, 1000);
Timer timer1 = new Timer();
timer1.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
synchronized (lock) {
Values.addValue(0);
}
}
}, 1000, 1000);
Timer timer2 = new Timer();
timer2.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
synchronized (lock) {
Values.printValues();
}
}
}, 1000, 1000);
}
}
这是Class I将数组存储在: 包主;
public class Values {
static int[] values = new int[1];
private final static Object lock = new Object();
public static void incrementValues() {
synchronized (lock) {
for (int i = 0; i < values.length; i++) {
values[i]++;
}
}
}
public static void addValue(int e) {
synchronized (lock) {
int[] temp = values;
values = new int[temp.length + 1];
for (int i = 0; i < temp.length; i++) {
values[i] = temp[i];
}
values[temp.length] = e;
}
}
public static void printValues() {
printValues(values);
}
public static void printValues(int[] values) {
synchronized (lock) {
}
StringBuilder sb = new StringBuilder();
for (int e : values) {
sb.append(e);
sb.append(' ');
}
System.out.println(sb.toString());
}
}
我应该得到的输出是一排数字,如:10 9 8 7 6 5 4 3 2 1 0
但取而代之的是21 21 19 18 17 16 15 15 14 13 11 10 9 8 7 6 6 5 4 2 1 0
我认为它必须直接在我面前,但我找不到它。
答案 0 :(得分:0)
您保证两个线程在同步中执行但不保证执行顺序。
因此 incrementValues 和 addValue 将处于竞争状态。您有重复的变量,因为有时会在 incrementValues 之前执行 addValue 。
如果您想保证连续订单没有任何重复,您应该实现一个门,以确保 incrementValues 和 addValue 以正确的顺序执行。
BTW:我认为Main类中的synchronized块是不必要的,因为你已经在Values类中进行了锁定。