【问题标题】:Interchangeable role of producer consumer threads in Java Multithreaded ProgramJava多线程程序中生产者消费者线程的可互换角色
【发布时间】:2017-12-25 05:31:27
【问题描述】:

目标:创建两个线程,使生产者和消费者线程可以互换工作,即如果第一个线程充当生产者,第二个线程充当消费者,反之亦然。

详细说明:它们通过缓冲区相互通信,存储一个整数大小。例如,如果第一个线程产生 1,那么第二个线程消耗它并产生 2,然后第一个线程消耗 2 并产生接下来的三个整数,消费者一个接一个地消耗它们。 之后两个线程都终止。 此外,两个线程都应该能够发起通信。

我尝试编写以下代码。

import java.util.Random;
class CommonItem {
boolean flag = false;
int arr[];

public synchronized void Send(String msg) {
    if (flag) {
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    System.out.println(msg);
    flag = true;
    notify();
}

public synchronized void Receive(String msg) {
    if (!flag) {
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    System.out.println(msg);
    arr = send_random();
    for (int item: arr) {
        System.out.println(item);
    }

    flag = false;
    notify();
}

synchronized int[] send_random(){
    int[] arr = new int[3];
    Random random= new Random();
    for (int i = 0; i < 3; i++) {
        arr[i]=random.nextInt(100);
    }
    return arr;
}
}
class T1 implements Runnable {
CommonItem Ci;

public T1(CommonItem Ci) {
    this.Ci = Ci;
    new Thread(this, "producer").start();
}

public void run() {
    while (true)
    Ci.Send("sent :1");
}
}

class T2 implements Runnable {
CommonItem Ci;

public T2(CommonItem m2) {
    this.Ci = m2;
    new Thread(this, "Consumer").start();
}

public void run() {
    while (true)
    Ci.Receive("received :2");
}
}
public class TestClass {

public static void main(String[] args) {

    CommonItem m = new CommonItem();
    new T1(m);
    new T2(m);
}
}

预期的输出是

sent :1

received :1

sent :2

received :2

sent :57 4 13

received :57 4 13

但我得到以下输出 输出

sent :1

received :2

57

4

13

如果代码中的任何更正或有关如何以替代方式解决给定问题的任何想法,请提出建议。提前谢谢您。

【问题讨论】:

  • 你如何使用等待是错误的。请参阅 oracle 教程,我也有多个关于它的 SO 答案。同样将锁定代码放在任务中而不是将其放在通用数据结构中似乎是个坏主意。你把应该简单的东西弄复杂了。无视代码约定也不好。

标签: java multithreading producer-consumer


【解决方案1】:
public class CommonItem {
    boolean receiver = false;
    List<Integer> list = new ArrayList<>();

    public void receive() throws InterruptedException {
        String name = Thread.currentThread().getName();
        synchronized (list) {
            while (list.isEmpty()) {
                list.notify();
                list.wait();
            }

            // Receive all elements
            System.out.printf("Receiving elements by %s:\t", name);
            for (int val : list) {
                System.out.print(val + "  ");
            }
            list.clear();
            System.out.println();
            list.notify();
            list.wait();
        }
    }

    public void send() throws InterruptedException {
        String name = Thread.currentThread().getName();
        synchronized (list) {
            while (!list.isEmpty()) {
                list.notify();
                list.wait();
            }
            // Sending elements
            int[] arr = get_random();
            System.out.printf("Sending elements by %s\t", name);
            for (int ele : arr) {
                list.add(ele);
                System.out.print(ele + "  ");
            }
            System.out.println();
            list.notify();
            list.wait();
        }
    }

    public int[] get_random() throws InterruptedException {
        int[] arr = new int[3];
        Random random = new Random();
        for (int i = 0; i < 3; i++) {
            arr[i] = random.nextInt(100);
        }
        Thread.sleep(1000);
        return arr;
    }
}

public class ThreadTask implements Runnable {

    private CommonItem item;
    private boolean receiver;

    public ThreadTask(CommonItem item, boolean receiver) {
        this.item = item;
        this.receiver = receiver;
    }

    public static void main(String[] args) {
        CommonItem item = new CommonItem();
        Thread t1 = new Thread(new ThreadTask(item, false), "First");
        Thread t2 = new Thread(new ThreadTask(item, true), "Second");
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        while (true) {
            try {
                if (receiver) {
                    item.receive();
                } else {
                    item.send();
                }
                receiver = !receiver;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

按前 25 6 57 发送元素
按秒接收元素:25 6 57
按秒发送元素 35 99 10
First 接收元素:35 99 10
按前 84 11 1 发送元素
按秒接收元素:84 11 1
按秒 68 91 53 发送元素
First 接收元素:68 91 53

【讨论】:

  • 谢谢。我得到了解决方案。
  • 没问题... :-)
【解决方案2】:
package java11;
import java.util.*;
import java.util.Random;
class CommonItem 
{
    boolean receiver = false;
    List<Integer> list = new ArrayList<>();
    int k=1;
    public void receive() throws InterruptedException 
    {
        String name = Thread.currentThread().getName();
        synchronized (list) 
        {
            while (list.isEmpty()) 
            {
                list.notify();
                list.wait();
            }
            // Receive all elements
            System.out.printf("Receiving elements by %s:\t", name);
            for (int val : list) 
            {
                System.out.print(val + "  ");
            }
            list.clear();
            System.out.println();
            list.notify();
            list.wait();
        }
    }

    public void send(int i) throws InterruptedException 
    {
        String name = Thread.currentThread().getName();
        synchronized (list) 
        {
            while (!list.isEmpty()) 
            {
                list.notify();
                list.wait();
            }
            // Sending elements
            int[] arr;
            if(i<3)
            {
                arr = get_random(k);
                k++;
            }
            else
            {
                arr = get_random1();
            }
            System.out.printf("Sending elements by %s\t", name);
            for (int ele : arr) 
            {
                list.add(ele);
                System.out.print(ele + "  ");
            }
            System.out.println();
            list.notify();
            list.wait();
        }
    }

    public int[] get_random(int k) throws InterruptedException  
    {
        int[] arr = new int[1];
        arr[0] = k;
        Thread.sleep(1000);
        return arr;
    }

    public int[] get_random1() throws InterruptedException 
    {
        int[] arr = new int[3];
        Random random = new Random();
        for (int i = 0; i < 3; i++) 
        {
            arr[i] = random.nextInt(100);
        }
        Thread.sleep(1000);
        return arr;
    }
}

public class Java11 implements Runnable 
{
    private CommonItem item;
    private boolean receiver;

    public Java11(CommonItem item, boolean receiver) 
    {
        this.item = item;
        this.receiver = receiver;
    }

    public static void main(String[] args) 
    {
        int choice;
        CommonItem item = new CommonItem();
        System.out.println("Who should start first?:Thread 1 or Thread 2");
        Scanner sc=new Scanner(System.in);
        choice=sc.nextInt();
        if(choice==1)
        {
            Thread t1 = new Thread(new Java11(item, false), "First");
            Thread t2 = new Thread(new Java11(item, true), "Second");
            t1.start();
            t2.start();
        }
        else if(choice==2)
        {
            Thread t1 = new Thread(new Java11(item, true), "First");
            Thread t2 = new Thread(new Java11(item, false), "Second");
            t1.start();
            t2.start();
        }
    }

    @Override
    public void run() 
    {
        int i=1;
        while (i<=3) 
        {
            try 
            {
                if (receiver) 
                {
                    item.receive();
                } 
                else 
                {
                    item.send(i);
                }
                receiver = !receiver;
            } 
            catch(InterruptedException e) 
            {
                e.printStackTrace();
            }
            i++; 
        }
    }
}

对 Sanit 的代码进行了细微更改,以获得问题陈述所要求的准确输出。

输出:

Who should start first?:Thread 1 or Thread 2
1
Sending elements by First   1  
Receiving elements by Second:   1  
Sending elements by Second  2  
Receiving elements by First:    2  
Sending elements by First   90  95  28  
Receiving elements by Second:   90  95  28  

Who should start first?:Thread 1 or Thread 2
2
Sending elements by Second  1  
Receiving elements by First:    1  
Sending elements by First   2  
Receiving elements by Second:   2  
Sending elements by Second  42  10  33  
Receiving elements by First:    42  10  33 

谢谢@Sanit。

已解决-@Kunjan Rana

【讨论】:

  • 这里注意两个线程之间的通信是从发送1开始的。
猜你喜欢
  • 1970-01-01
  • 2013-11-17
  • 1970-01-01
  • 2012-04-30
  • 1970-01-01
  • 2012-10-13
  • 2014-10-13
  • 2017-02-01
  • 1970-01-01
相关资源
最近更新 更多