使用线程生产并消费到列表中?

时间:2019-02-16 06:35:01

标签: java multithreading

我创建了两个单独的线程,一个用于写入列表,另一个用于从列表中删除。

package com.produ.consu;

public class Test {

    public static void main(String[] args) {

        Operations operations = new Operations();
        Runnable r1 = new ThreadsClass(operations);
        Runnable r2 = new ThreadsClass(operations);
        Thread t1 = new Thread(r1);
        Thread t2 = new Thread(r2);
        t1.setName("READ");
        t2.setName("WRITE");
        t1.start();
        t2.start();
    }
}

以上是我在其中创建线程的Test类。

package com.produ.consu;

public class ThreadsClass implements Runnable {

    Operations operations;

    ThreadsClass(Operations operations){
        this.operations=operations;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        if(Thread.currentThread().getName().equals("WRITE")) {
            operations.writeList();
        }
        else {
            operations.readList();

        }
    }

}

以上是基于线程名称调用同步方法的类:

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

public class Operations {

    List<Integer> list=null;
    int count=0;    
    boolean flag;
    Operations(){
        list=new ArrayList<>();
        flag=true;
    }

    public  synchronized void writeList() {
        // TODO Auto-generated method stub
        while(true) {

            if(flag) {
                count++;
                list.add(count);
                System.out.println("inise if block...."+Thread.currentThread().getName());
                System.out.println(list);
                flag=false;
                try {
                    wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            else {
                notify();
            }

        }
    }

    public synchronized void readList() {
        // TODO Auto-generated method stub
        while(true) {
            if(!flag) {
                Integer i = list.remove(0);
                System.out.println(i+"..removed at index by"+Thread.currentThread().getName());
                flag=true;
                notify();
            }
            else {
                try {
                    wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

    }

}

上面是我提到的功能。 因此,写线程不必将元素写到列表中,直到第二个线程将其删除为止。 一旦删除,第二则应通知1st并等待直到元素插入。 但是得到...

  

表示是否受阻。...WRITE [1]

甚至没有删除,它必须是一个连续的过程。 给我有关给定代码的建议。

3 个答案:

答案 0 :(得分:1)

您还应该在wait()块内else,否则,如果while不满意并且另一个线程无法获得if,则notify将继续运行机会执行。

执行读/写操作后,线程应调用 public synchronized void writeList() { while (true) { if (flag) { count++; list.add(count); System.out.println("inise if block...." + Thread.currentThread().getName()); System.out.println(list); flag = false; try { notify(); //notify the read thread that write is complete wait(); // go into the waiting state so that no further write is done until the current element is removed by the read thread. } catch (InterruptedException e) { e.printStackTrace(); } } else { try { wait(); //wait in else, otherwise while will run endlessly } catch (InterruptedException e) { e.printStackTrace(); } } } } public synchronized void readList() { while (true) { System.out.println("in read"); if (!flag) { Integer i = list.remove(0); System.out.println(i + "..removed at index by" + Thread.currentThread().getName()); flag = true; try { notify(); //notify write thread that read is complete wait(); //go into wait until new element is inserted } catch (InterruptedException e) { e.printStackTrace(); } } else { try { wait(); //wait in else otherwise while runs endlessly } catch (InterruptedException e) { e.printStackTrace(); } } } } 来唤醒另一个线程,并且其本身应进入等待状态。

{{1}}

答案 1 :(得分:0)

您应该将方法同步替换为更精细的同步:用一个同步块包装访问列表和更新计数的操作。

或者,使用链接的阻塞队列在线程之间传递“消息”(或者,在更高级的方案中,使用Akka,Kafka,zeromq等消息传递解决方案或其他类似解决方案)

答案 2 :(得分:0)

由于一次只能添加一个要素,因此也可以使用交换器。 看看Java并发包。

import java.io.IOException;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Foo {

    public static void main(String[] args) throws IOException, InterruptedException {

        final Exchanger<Integer> exchanger = new Exchanger<>();    
        ExecutorService executorService = Executors.newCachedThreadPool();

        executorService.execute(() -> {
            // producer
            int count = 0;
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    exchanger.exchange(count++);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        executorService.execute(() -> {
            // reader
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    System.out.println("consume " + exchanger.exchange(null));
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        System.in.read();

        executorService.shutdownNow();
        executorService.awaitTermination(10, TimeUnit.SECONDS);
        System.out.println("Shut down");
    }
}