生产者 - 消费者模式设计问题

时间:2013-12-21 20:40:38

标签: java multithreading algorithm producer-consumer

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

i.e.

我使用此实现:

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;
    }

}

main_class

   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()) {
        }

    }

}

computingThread

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;
    }
}

这是我要做的事情:

我正在尝试使用多线程计算树的有限值的parllel计算机(每个节点获取两个值,根据他的opreator生成结果,将其传递给树...直到根被caculted )。我所做的是设置一个固定数量的空格队列。

我在构建树时将叶子插入队列。然后我启动一个消费者,它接受每个叶子,计算它,将结果传递给他父亲的右边,当两个entreis插入父节点时,它也会进入队列,依此类推......直到root是cacluted)。

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

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

有没有人对此有任何解决方案?

和另一个问题?是考虑parrlel计算?这意味着如果我设置一个大小为2的队列,这是否意味着我将只用两个线程进行所有计算(因为我想设置的就像某台计算机的核心CPU数)。

谢谢,对不起我的拼写错误。

1 个答案:

答案 0 :(得分:0)

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

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

然后我会把它们组合起来构建我的电路,就像这样:

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

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

希望我帮忙!