当前位置: 首页 > 知识库问答 >
问题:

ArrayList即使使用同步块也不是线程安全的?

韦繁
2023-03-14

我尝试使用ArrayList解决生产者和消费者问题(我知道ArrayList是nt threadsafe),我确保使用synchronized关键字放置列表,但仍然进入ConcurrentModificationException。这就是错误

启动生产者请提供作业详细信息:TestJob作业完成:TestJob Exception位于java.util.ArrayList$itr.checkforcoModification(未知源)位于test.thread.consumer.run(consumer.java:25)位于java.lang.thread.run(未知源)的java.util.arrayList$itr.next(未知源)

下面是我的代码:

    package test.thread;

import java.util.List;
import java.util.Scanner;

public class Producer implements Runnable {

    private List<String> jobs = null;

    public Producer(List<String> jobs) {
        this.jobs = jobs;
    }

    @Override
    public void run() {

        System.out.println("Starting Producer");
        while(true)
        {
            synchronized (jobs) {
                try {
                if (jobs.isEmpty()) {


                        System.out.println("Please provide the job details: ");
                        Scanner scanner = new Scanner(System.in);
                        String job = scanner.nextLine();
                        jobs.add(job);
                        scanner.close();
                        jobs.notifyAll();
                        Thread.sleep(4000);

                } else {
                    jobs.wait();
                }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }

    }

}


package test.thread;

import java.util.List;

public class Consumer implements Runnable {

    private List<String> jobs = null;

    public Consumer(List<String> list) {
        this.jobs = list;
    }

    @Override
    public void run() {

        while(true)
        {
            synchronized (jobs) {
                try {
                    if (jobs.isEmpty()) {

                        jobs.wait();

                    } else {
                        for (String job : jobs) {
                            System.out.println("Job completed: " + job);
                            jobs.remove(job);
                            Thread.sleep(2000);
                        }

                        jobs.notifyAll();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }

        }

    }

}



package test.thread;

import java.util.ArrayList;
import java.util.List;

public class TestThread {

    public static void main(String...strings )
    {

        List<String> list = new ArrayList<String>();
        Producer producer = new Producer(list);
        Consumer consumer = new Consumer(list);
        Thread prodThread = new Thread(producer, "producer");
        Thread consThread = new Thread(consumer, "consumer");
        prodThread.start();
        consThread.start();
    }




}

共有1个答案

班安平
2023-03-14

尽管您得到了ConcurrentModificationException,但问题根本不是由多线程引起的。

事实上,这是有问题的代码:

for (String job : jobs) {
    System.out.println("Job completed: " + job);
    jobs.remove(job);
    Thread.sleep(2000);
}

for循环将在作业上使用迭代器,同时直接(从结构上)修改作业(即不通过迭代器)。这意味着迭代器不再定义良好,它抛出这个异常来告诉您有关它的情况。

Iterator<String> jobIterator = job.iterator();
while (jobIterator.hasNext()) {
  String job = jobIterator.next();
  // ... stuff ...
  jobIterator.remove(); // remove the last object that was returned by next()
}
 类似资料:
  • 我要创建一个程序,给定N个线程,这些线程可以在队列中插入或删除一个元素,但是线程访问队列是有条件的: null 我用同步块做的,就像这样: run void很简单,它只是在插入或删除元素时永远循环。 我的问题是,在不使用synchronized的情况下,我如何遵循那个条件? 没有同步块,怎么可能保证互斥呢? 编辑:我不能使用类似于同步的东西(就像锁一样)

  • 我是java新手。我有点混淆了线程安全和同步。线程安全意味着一个方法或类实例可以被多个线程同时使用,而不会出现任何问题。其中同步意味着一次只能有一个线程运行。 那么它们是如何相互关联的呢?

  • 我编写这个程序是为了模拟。 程序很简单。我们有两个线程。主线程确实使用“test”对象在块中将标志“Stop”更改为true。 我预计一旦主线程将此设置为true,就会使while循环终止。但是,即使主线程将标志设为true,另一个线程也看不到最新的值(即使它是在同步块中更新的)。 奇怪的是,当我取消注释(在里面)时,线程确实“看到”了最新的值并终止了。 我不明白这种行为。为什么其他线程无法看到在

  • 问题内容: 我有一个正在实例化并填充在后台线程上的代码(我用它来存储数据)。同时,可以在主线程上对其进行访问,并通过使用foreach对其进行迭代。因此,这显然可能导致引发异常。 我的问题是使此类类字段成为线程安全的而不每次都复制它或不使用标志的最佳实践是什么? 问题答案: 通常,对不是线程安全的数据结构进行并发操作是一个非常糟糕的主意。您无法保证将来的实现不会改变,这可能会严重影响应用程序的运行

  • 让我们假设这样: 存在单个ArrayList 列表由多个线程访问。线程可以添加元素并迭代所有元素。 所有访问都是外部同步的。因此两个线程不可能同时访问列表。 查看ArrayList源代码,我们可以看到size和elementData字段不是易变的: 另外,让我们看看add方法: 这样的事情会发生吗? 假设列表有4个元素。 线程A添加新元素。大小更新为5。 线程B添加新元素。Size被缓存,线程B看

  • 问题内容: 有人可以告诉我线程开始执行的顺序吗?我写了下面的代码 还有这个 当我执行此代码时,我得到许多不同的输出。 另一个, 为什么会这样呢?线程顺序永远不会相同吗?如果有人可以给我一些有关线程和示例基础的知识,那就太好了。PS:我是线程的新手,这是我的第一个线程程序。提前致谢。 问题答案: 当我执行此代码时,我得到许多不同的输出。 这是预期的。该顺序未定义,并且随着线程开始运行并由OS进行线程