【问题标题】:Producer–consumer pattern deisgn issue生产者-消费者模式设计问题
【发布时间】:2023-03-14 03:55:01
【问题描述】:

我正在努力实现一棵代表电动马戏团的树(没有任何圆圈,如图所示)

我使用这个实现:

Binary_Oprtator

public abstract class Binary_Oprtator {
        abstract int calc(int x, int y);

        @Override
        public String toString() {
        return super.toString().substring(0, super.toString().indexOf('@'));
        }
}

还有门

public class and extends Binary_Oprtator {
        public int calc(int x, int y){
            return (x&y);
        }
}

或门

public class or extends Binary_Oprtator {
        public int calc(int x, int y){
            return (x|y);
        }
}

gate_node

public class gate_node {
    gate_node father_c;
    gate_node right_c, left_c;
    Binary_Oprtator op;
    int value;
    int right_v, left_v;
    int array_index;
    int arr_size;
    boolean leaf;
    boolean isRightChild;

    public gate_node(Binary_Oprtator op, int array_index, int arr_size, boolean right) {
        this.array_index = array_index;
        this.arr_size = arr_size;
        this.left_c = null;
        this.right_c = null;
        this.op = op;
        right_v = left_v = -1;
        this.leaf = false;
        this.isRightChild = right;

    }

    void set_left_son(Binary_Oprtator op) {
        this.left_c = new gate_node(op, array_index, arr_size / 2,false);
        this.left_c.father_c = this;
        this.left_c.leaf = false;
        this.left_c.isRightChild = false;
    }

    void set_right_son(Binary_Oprtator op) {
        this.right_c = new gate_node(op, array_index + arr_size / 2,
                arr_size / 2,true);
        this.right_c.father_c = this;
        this.right_c.leaf = false;
        this.right_c.isRightChild = true;
    }

    void set_left_son_as_leaf(Binary_Oprtator op) throws InterruptedException {
        this.left_c = new gate_node(op, array_index, arr_size / 2,false);
        this.left_c.father_c = this;
        this.left_c.leaf = true;
        this.left_c.left_v = main_class.arr[array_index];
        this.left_c.right_v = main_class.arr[array_index + 1];
        this.left_c.isRightChild = false;

        main_class.queue.put(this.left_c);
    }

    void set_right_son_as_leaf(Binary_Oprtator op) throws InterruptedException {
        this.right_c = new gate_node(op, array_index + arr_size / 2,
                arr_size / 2,true);
        this.right_c.father_c = this;
        this.right_c.left_v = main_class.arr[array_index + 2];
        this.right_c.right_v = main_class.arr[array_index + 3];
        this.right_c.leaf = true;
        this.right_c.isRightChild = true;

        main_class.queue.put(this.right_c);
    }

    gate_node get_left() {
        return this.left_c;
    }

    gate_node get_right() {
        return this.right_c;
    }

    int compute() {
        /*
         * The following use of a static sInputCounter assumes that the
         * static/global input array is ordered from left to right, irrespective
         * of "depth".
         */
        final int left, right;
        if (this.left_c.leaf != true) {
            left = this.left_c.compute();
        } else {
            left = this.left_c.op.calc(this.left_c.left_v, this.left_c.right_v);
        }
        if (this.right_c.leaf != true) {
            right = this.right_c.compute();

        } else {
            right = this.right_c.op.calc(this.right_c.left_v,
                    this.right_c.right_v);
        }

        return op.calc(left, right);
    }

    int compute_with_print() {
        /*
         * The following use of a static sInputCounter assumes that the
         * static/global input array is ordered from left to right, irrespective
         * of "depth".
         */

        final int left, right;
        System.out.print(this.op + "(");

        if (null != this.left_c) {
            left = this.left_c.compute_with_print();
            System.out.print(",");
        } else {
            left = main_class.arr[array_index];
            System.out.print(left + ",");
        }

        if (null != this.right_c) {
            right = this.right_c.compute_with_print();
            System.out.print(")");
        } else {
            right = main_class.arr[array_index + 1];

            System.out.print(right + ")");
        }

        return op.calc(left, right);
    }

}

public class tree  {
    gate_node head;

    public tree(Binary_Oprtator op,int array_index,int arr_size) {
        this.head  = new gate_node(op,array_index,arr_size,true);
        head.father_c=null;

    }
    void calc_head_value(){
        int t_value = head.op.calc(head.left_v,head.right_v);
    /*  System.out.println(head.left_v+" "+head.op.toString()+" "+head.right_v+" = "+head.op.calc(head.left_v,head.right_v));
*/      head.value = t_value;
    }
    int compute() {
        return head.compute();
    }
    int compute_with_print(){
        return head.compute_with_print();
    }



    void set_left_son(Binary_Oprtator op){
        head.left_c = new gate_node(op,head.array_index,head.arr_size/2,false);
        head.left_c.father_c=head;

    }

    void set_right_son(Binary_Oprtator op){
        head.right_c = new gate_node(op,head.array_index + head.arr_size/2,head.arr_size/2,true);
        head.right_c.father_c=head;

    }

    void set_right_son_as_leaf(Binary_Oprtator op) throws InterruptedException {
        head.right_c = new gate_node(op,head.array_index,head.arr_size/2,false);
        head.right_c.father_c=head;
        head.right_c.father_c = head;
        head.right_c.left_v = main_class.arr[head.array_index + 2];
        head.right_c.right_v = main_class.arr[head.array_index + 3];
        head.right_c.leaf = true;
        head.right_c.isRightChild = true;

        main_class.queue.put(head.right_c);
    }

    void set_left_son_as_leaf(Binary_Oprtator op) throws InterruptedException {
        head.left_c = new gate_node(op, head.array_index, head.arr_size / 2,false);
        head.left_c.father_c = head;
        head.left_c.leaf = true;
        head.left_c.left_v = main_class.arr[head.array_index];
        head.left_c.right_v = main_class.arr[head.array_index + 1];
        head.left_c.isRightChild = false;

        main_class.queue.put(head.left_c);
    }

    gate_node get_left(){
        return head.left_c;
    }

    gate_node get_right(){
        return head.right_c;
    }

}

主类

   import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class main_class {
    public static int arr[] = { 1, 0, 0, 0, 1, 0, 0, 1 };

    static final BlockingQueue<gate_node> queue = new ArrayBlockingQueue<>(6);

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

/*************************************
 * compute using multi threads
 ************************************/
        System.out.println("compute using Multi threading");

        //start a consumer... wait for nodes to be insert into the queue
        Consumer consumer = new Consumer();
        consumer.start();


        tree t = new tree(new and(), 0, arr.length);
        t.set_left_son(new or());
        t.get_left().set_left_son_as_leaf(new and());
        t.get_left().set_right_son_as_leaf(new or());

        t.set_right_son(new and());
        t.get_right().set_left_son_as_leaf(new or());
        t.get_right().set_right_son_as_leaf(new or());  

        consumer.join();
        t.calc_head_value();    //calc the head
        System.out.println("The result is: " + t.head.value);
        System.out.println();


    /******************************
     * compute with a single thread
    ********************************/

        System.out.println("compute with a single thread");
        int res = t.compute();
        System.out.println("The result is: " + res);


    /***********************************************
     * printing a arithmatic expression of the tree
    *************************************************/
        System.out.println();
        t.compute_with_print();






    }
}

消费者

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Consumer extends Thread {

    Consumer() {

    }

    @Override
    public void run() {
        gate_node temp;

        // the threads pool parts
        ExecutorService executor = Executors.newFixedThreadPool(4);

        try {
            while ((temp = main_class.queue.take()).father_c != null) {
                Runnable worker = new computingThread(temp);
                executor.execute(worker);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        executor.shutdown();
        while (!executor.isTerminated()) {
        }

    }

}

计算线程

public class computingThread implements Runnable {
    gate_node head;

    int t_value;

    public computingThread(gate_node head) {
        this.head = head;
        this.t_value = -1;
    }

    @Override
    public void run() {
        /* System.out.println("Start: "+this.hashCode()); */
        t_value = head.op.calc(head.left_v,head.right_v);

/*      System.out.println("thread: "+this.hashCode()+" is running ==> "+head.left_v+" "+head.op.toString()+" "+head.right_v+" = "+head.op.calc(head.left_v,head.right_v));
*/      head.value = this.t_value;

        // update the father

        if (head.isRightChild == true) { //update right fathers entire
            head.father_c.right_v = t_value;

            /*System.out.println("isRightChild");*/
        } else { //update left fathers entire
            head.father_c.left_v = t_value;
        }

        if ((head.father_c.right_v != -1) && (head.father_c.left_v != -1)){ //father is ready to compute-> to the queue!
            try {
                main_class.queue.put(head.father_c);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            }
    /*  try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }*/
    /*  System.out.println("thread: "+this.hashCode()+" is done!");
*/      return;
    }
}

这是我想要做的:

我正在尝试做一个并行计算,它使用多线程来计算树的有限值(每个节点获取两个值,根据他的操作符产生一个结果,将它传递给树..直到根被计算出来)。我所做的是设置一个固定数量的空间队列。

我在构建树时将叶子插入队列。然后我启动一个消费者,获取每个叶子,计算它,将结果传递到他父亲的右条目上,当两个条目都插入父亲节点时,它也进入队列,依此类推..直到根被计算)。

唯一的问题是我不能使用小于树中叶子数量的队列,我不知道为什么。

也许是因为在我构建树时,我将叶子插入到树中,如果队列比叶子小,我正在做:main_class.queue.put(this.right_c); 当队列已经满时,这会导致计划等到队列上的空间被释放,这不会发生(因为我还没有启动线程)。

有没有人可以解决这个问题?

还有一个问题?那是考虑并行计算吗?意思是如果我设置一个大小为 2 的队列,这是否意味着我将只用两个线程完成所有计算(因为我要设置的就像某台计算机的核心 CPU 数量)。

感谢并为我的拼写错误感到抱歉。

【问题讨论】:

  • 您的代码不易阅读。所以只是第一次快速扫描,主线程旁边只有一个线程。它不是真正的并行编程,因此处理以串行方式运行。我想它会导致你的问题。

标签: java multithreading algorithm producer-consumer


【解决方案1】:

我认为您以比实际需要的更复杂的方式对其进行建模。我不会将我的建模建立在树上。电路并不总是一棵树。您可以将多个节点用作电路输出,对吗?

我会将我的建模基于门节点。我会有一个Gate 类,它有两个输入和一个输出。输入和输出的类型为GateValue。如果门是andor 门,则将使用不同的方式计算输出。

然后我会将它们组合起来构建我的电路,如下所示:

gate1.Input1 = gate2.Output
gate1.Input2 = gate3.Output

等等

然后,我将计算最后一个门(整个电路的输出)的值,这将导致其他门计算它们的值。这样,您就不需要“并行”计算机制。只要您的电路中没有反馈回路,就可以正常工作。

希望我能帮上忙!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-27
    • 1970-01-01
    相关资源
    最近更新 更多