同时在列表中添加和删除元素

时间:2019-04-14 13:42:12

标签: java multithreading

我想创建两个线程,一个线程将元素添加到ArrayList(或向量)中,另一个线程同时从此列表中删除元素。例如,如果thread1将20个元素添加到列表中,则thread2开始同时删除,直到删除了全部元素,但是这两个线程必须同时工作。

我写了一个生产者(添加到列表中)线程。在此线程中,当添加到列表中的元素数量大于5或任意数量时,因此必须启动新线程,但是在这里我被卡住了。我会指出我被困住的地方。

public class Test{

public static void main(String[] args) {

    Data d = new Data();
    Thread t = new Thread(new producer(d));
    t.start();
}

}
class producer implements Runnable{

Data d;
Data d2;
Object lck;

public producer(Data dd)
{
    d=dd;
}
@Override
public void run()
{
    for (int i=0;i<100;++i ) {
        synchronized (d){
            d.a.add(i);
            // if i is greater than 5,
            // start consumer thread 
            // which remove elements from ArrayList.
            // but how ??
            Thread t = new Thread(new Runnable(){
                @Override
                public void run()
                {
                    //if(d.a.isEmpty())
                    //wait the adder thread 
                }
            });
            t.start();      
        }
    }
}

}
class Data{
  ArrayList<Integer> a; // or vector
  public Data()
  {
      a = new ArrayList<>();
  } 
}

我该如何实现一个删除器线程,该线程与加法器线程同时删除列表中的所有元素并进行同步?

2 个答案:

答案 0 :(得分:0)

您可以尝试并发java软件包。 https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CopyOnWriteArrayList.html

您正在线程中使用同步块,这种情况下无济于事。集合或共享数据中的方法应该同步,因为它将被多个线程访问

答案 1 :(得分:0)

在您的代码中,您正在同步块内的生产者类中创建100个使用者线程。这不是通过多线程利用并行性的有效方法。您正在为要使用的一种数据创建一个线程。一旦消耗完数据,您的线程将处于DEAD状态,将不会消耗其他传入数据,这既浪费资源,又需要更多时间来解决问题。

请参考以下代码来解决您的消费者生产者问题。

import java.util.*;

class Data {
    final List<Integer> a;

    public Data() {
        a = new ArrayList<>();
    }
}

public class Producer implements Runnable {

    private final Data data;

    public Producer(Data data) {
        this.data = data;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            synchronized (data) {
                data.a.add(i);
            }
        }
    }
}

public class Consumer implements Runnable {

    private Data data;
    private boolean isThreadEnabled = true;

    public Consumer(Data data) {
        this.data = data;
    }

    @Override
    public void run() {
        while (isThreadEnabled) {
            synchronized (data) {
                if (!data.a.isEmpty()) {
                    System.out.println(data.a.remove(0));
                }
            }
        }
    }

    public void stopConsumer() {
        isThreadEnabled = false;
    }
}

public class ThreadsMain {

    public static void main(String args[]) {

        try {
            Data data = new Data();
            Consumer consumerRunnable = new Consumer(data);
            Thread producer = new Thread(new Producer(data));
            Thread consumer = new Thread(consumerRunnable);

            producer.start();
            consumer.start();
            producer.join();

            try {
                //wait for consumer to consume data and then stop the thread
                Thread.sleep(1000);
                consumerRunnable.stopConsumer();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}