Java 访问不同线程上的列表的输出是什么?
我有一个Java 访问不同线程上的列表的输出是什么?,java,multithreading,synchronized,Java,Multithreading,Synchronized,我有一个ArrayList的Strings,两个线程同时访问该列表。 以下代码段的输出将是什么?为什么 public static void main(String[] args) { final ArrayList<String> list = new ArrayList<String>(); for (int i = 0; i < 100; i++) { list.add("Number" + i); } ne
ArrayList
的String
s,两个线程同时访问该列表。
以下代码段的输出将是什么?为什么
public static void main(String[] args) {
final ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < 100; i++) {
list.add("Number" + i);
}
new Thread() {
public void run() {
for (String s : list) {
System.out.println(s);
}
}
}.start();
new Thread() {
public void run() {
list.remove("Number5");
}
}.start();
}
publicstaticvoidmain(字符串[]args){
最终ArrayList=新ArrayList();
对于(int i=0;i<100;i++){
列表。添加(“编号”+i);
}
新线程(){
公开募捐{
用于(字符串s:列表){
系统输出打印项次;
}
}
}.start();
新线程(){
公开募捐{
列表。删除(“编号5”);
}
}.start();
}
我尝试使用相同的代码使
Arraylist
使用Collections.synchronizedList(list)
进行同步。它仍在抛出java.util.ConcurrentModificationException
您正在迭代(在第一个线程中)和更新(在第二个线程中)两个不同线程中相同的列表
对象,因此总是存在(可能性)它将抛出java.util.ConcurrentModificationException
java迭代器本质上是快速失效的,因此,一旦他们意识到下划线结构已被更改,就会出现ConcurrentModificationException
异常
如果您想为您的需要使用相同的列表对象,您可以考虑在代码< >运行< /COD>方法> < /P>中使用<代码>同步(列表)< /代码>进行同步。
public void run() {
synchronized(list) {
for (String s : list) {
System.out.println(s);
}
}
}
public void run() {
synchronized(list) {
list.remove("Number5");
}
}
我认为你应该使用Vector
而不是ArrayList
作为ThreadSafe
的工具,并使用Iterator
浏览列表。你可以使用关键字锁定列表
对象
同步关键字
其总体目的是只允许一个线程
在一段时间内进入特定的代码段,从而允许我们
例如,保护变量或数据不被
来自不同线程的同时修改
所以这应该对你有用:
public static void main(String[] args) {
...
new Thread() {
public void run() {
synchronized(list){
for (String s : list) {
System.out.println(s);
}
}
}
}.start();
new Thread() {
public void run() {
synchronized(list){
list.remove("Number5");
}
}
}.start();
}
NB:这取决于您想要的逻辑。顺便问一下,您是希望在迭代时从列表中删除,还是希望从列表中删除?您希望这两个任务按顺序进行吗?的Javadoc明确指出:
用户在对返回的列表进行迭代时,必须手动同步该列表:
List list = Collections.synchronizedList(new ArrayList());
...
synchronized (list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
不遵循此建议可能会导致不确定性行为
由于在该代码中,当您在列表
上进行迭代时(在不同的线程中,但它是列表
的同一实例),您将从该列表中删除,因此将抛出ConcurrentModificationException
使用Collections.synchronizedList
,以下代码将正常运行
final List<String> list = Collections.synchronizedList(new ArrayList<String>());
for (int i = 0; i < 100; i++) {
list.add("Number" + i);
}
new Thread() {
public void run() {
synchronized (list) {
for (String s : list) {
System.out.println(s);
}
}
}
}.start();
new Thread() {
public void run() {
synchronized (list) {
list.remove("Number5");
}
}
}.start();
final List=Collections.synchronizedList(new ArrayList());
对于(int i=0;i<100;i++){
列表。添加(“编号”+i);
}
新线程(){
公开募捐{
已同步(列表){
用于(字符串s:列表){
系统输出打印项次;
}
}
}
}.start();
新线程(){
公开募捐{
已同步(列表){
列表。删除(“编号5”);
}
}
}.start();
你的意思是问,“这个函数是线程安全的吗?”我也是:我在寻找它的用途。如果需要,我想我们将不得不在两个线程之间交错任务。此外,添加和删除类似于生产者-消费者问题(打印整个列表需要锁定整个列表对象,这取决于开发人员的意图。)是的,这完全取决于开发人员的意图。但开发商并没有这样评论…-)