我想创建两个线程,一个线程将元素添加到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<>();
}
}
我该如何实现一个删除器线程,该线程与加法器线程同时删除列表中的所有元素并进行同步?
答案 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();
}
}
}