【发布时间】: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