Java lambdas LinkedBlockingQueue 意外行为
Java lambdas LinkedBlockingQueue unexpected behaviour
我正在尝试从使用 lambda 创建的线程向 t linkedBlockingQueue 添加元素,当我使用 take 方法轮询队列时,我可以看到从线程输入的最后一个值覆盖了以前的值。
代码如下:-
public List<EntryBarricade> entryBarricades() {
List<EntryBarricade> entryBarricades = new ArrayList<>();
EntryBarricade entryBarricade;
Runnable runnable;
for (int i =0;i<=1;i++) {
EntryRequest entryRequest = new EntryRequest("Barricade-"+i);
runnable = new Runnable() {
@Override
public void run() {
ExecutorService entryGate1 = Executors.newSingleThreadExecutor();
for (int j =0;j<=1;j++) {
entryGate1.submit(() -> {
entryRequest.setVehicleId(Thread.currentThread().getName()
+ " " + new Double(Math.random()));
entryRequestQueuingService.Queue(entryRequest);
});
}
}
};
entryBarricade = new EntryBarricade("Barricade-"+i, runnable);
entryBarricades.add(entryBarricade);
}
return entryBarricades;
}
轮询队列后,我得到以下信息:-
请求{barricadeId='Barricade-0', vehicleId='pool-2-thread-1 0.9091480024731418'}
请求{barricadeId='Barricade-0', vehicleId='pool-2-thread-1 0.05687657229049259'}
请求{barricadeId='Barricade-1', vehicleId='pool-3-thread-1 0.7978996055410615'}
请求{barricadeId='Barricade-1', vehicleId='pool-3-thread-1 0.2734508504023724'}
请求{barricadeId='Barricade-0', vehicleId='pool-2-thread-1 0.05687657229049259'}
请求{barricadeId='Barricade-0', vehicleId='pool-2-thread-1 0.05687657229049259'}
请求{barricadeId='Barricade-1', vehicleId='pool-3-thread-1 0.2734508504023724'}
请求{barricadeId='Barricade-1', vehicleId='pool-3-thread-1 0.2734508504023724'}
我不确定发生了什么。
有人可以解释一下这种行为吗??
谢谢,
阿马尔
我假设这里存在问题:您的 entryRequest 是在循环的每次迭代中创建的(在主线程中)。因此,当线程池执行程序调用您的 lamdba 时,它可能已经更改。您绝对无法控制谁访问此变量。
与其构造一个匿名的 Runnable class,不如编写您自己的 Runnable 实现,将 entryRequest 作为参数传递给它(例如通过构造函数或 setter)并让 运行方法然后对这个传递的变量进行操作。这确保每个线程都在其自己的 entryRequest 实例上运行。
我正在尝试从使用 lambda 创建的线程向 t linkedBlockingQueue 添加元素,当我使用 take 方法轮询队列时,我可以看到从线程输入的最后一个值覆盖了以前的值。
代码如下:-
public List<EntryBarricade> entryBarricades() {
List<EntryBarricade> entryBarricades = new ArrayList<>();
EntryBarricade entryBarricade;
Runnable runnable;
for (int i =0;i<=1;i++) {
EntryRequest entryRequest = new EntryRequest("Barricade-"+i);
runnable = new Runnable() {
@Override
public void run() {
ExecutorService entryGate1 = Executors.newSingleThreadExecutor();
for (int j =0;j<=1;j++) {
entryGate1.submit(() -> {
entryRequest.setVehicleId(Thread.currentThread().getName()
+ " " + new Double(Math.random()));
entryRequestQueuingService.Queue(entryRequest);
});
}
}
};
entryBarricade = new EntryBarricade("Barricade-"+i, runnable);
entryBarricades.add(entryBarricade);
}
return entryBarricades;
}
轮询队列后,我得到以下信息:-
请求{barricadeId='Barricade-0', vehicleId='pool-2-thread-1 0.9091480024731418'} 请求{barricadeId='Barricade-0', vehicleId='pool-2-thread-1 0.05687657229049259'} 请求{barricadeId='Barricade-1', vehicleId='pool-3-thread-1 0.7978996055410615'} 请求{barricadeId='Barricade-1', vehicleId='pool-3-thread-1 0.2734508504023724'}
请求{barricadeId='Barricade-0', vehicleId='pool-2-thread-1 0.05687657229049259'} 请求{barricadeId='Barricade-0', vehicleId='pool-2-thread-1 0.05687657229049259'} 请求{barricadeId='Barricade-1', vehicleId='pool-3-thread-1 0.2734508504023724'} 请求{barricadeId='Barricade-1', vehicleId='pool-3-thread-1 0.2734508504023724'}
我不确定发生了什么。 有人可以解释一下这种行为吗??
谢谢,
阿马尔
我假设这里存在问题:您的 entryRequest 是在循环的每次迭代中创建的(在主线程中)。因此,当线程池执行程序调用您的 lamdba 时,它可能已经更改。您绝对无法控制谁访问此变量。
与其构造一个匿名的 Runnable class,不如编写您自己的 Runnable 实现,将 entryRequest 作为参数传递给它(例如通过构造函数或 setter)并让 运行方法然后对这个传递的变量进行操作。这确保每个线程都在其自己的 entryRequest 实例上运行。