package cn.edu.gxu;
/*
* 本程序意在使用多线程方法求一组数据的和
* 也相当于一种归约运算
* */
public class SumByThreads {
public static final int NUM_THREADS = 4; //定义线程数量
public static SumThread[] r = new SumThread[NUM_THREADS];
public static int[] a = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; //sum = 136
public static void main(String[] args) throws Exception {
int i;
int sum = 0;
Thread[] t = new Thread[NUM_THREADS];
//将数据分为NUM_THREADS段,交给每个线程分别处理
for(i=0; i<NUM_THREADS; i++) {
r[i] = new SumThread(i,a.length);
t[i] = new Thread(r[i]);
t[i].start();
//t[i].join(); //join()方法要求t[i]执行完毕后才能执行其他的步骤,
//加上这句话就相当于单线程执行
}
/* 线程启动后执行加法操作,如何将计算即结果汇总到一起是本程序要解决的难点,
* 主要是子线程何时结束我们无法确定,下面就是先判断子线程是否活着,
* 如果活着就等它结束,再将它的结果汇总。
* 不足之处在于,有的线程很早就结束了,但是遍历的时候还没检查到他,只好等待,
* 在等待的时间里本可以做加法,但却什么都没干,浪费了时间,
* 希望阅读本程序的同学能有好的方法解决这个问题。
* */
for(i=0; i<NUM_THREADS; i++) {
if(t[i].isAlive()){
t[i].join();
}
sum += r[i].getResult();
}
System.out.println(Thread.currentThread().getName() + " sum = " + sum);
}
public static class SumThread implements Runnable {
private int segNum; //数据段的序号
private int num; //数组中元素数量
private int result = 0;
public SumThread(int segNum,int num) {
this.segNum = segNum;
this.num = num;
}
@Override
public void run() {
int start,end;
//划分数据块的起点和终点
start = (int) (((float)(num/NUM_THREADS)) * segNum);
end = (int) ((float)(num/NUM_THREADS) * (segNum + 1));
if(segNum == NUM_THREADS - 1) {
end = num;
}
for(int i=start; i<end; i++) {
result = result + a[i];
}
System.out.println(Thread.currentThread().getName() + " sum = " + result);
}
public int getResult() {
return result;
}
}
}
运行结果:
Thread-0 sum = 10
Thread-3 sum = 58
Thread-2 sum = 42
Thread-1 sum = 26
main sum = 136
Thread-0 sum = 10
Thread-1 sum = 26
Thread-2 sum = 42
Thread-3 sum = 58
main sum = 136
Thread-0 sum = 10
Thread-2 sum = 42
Thread-3 sum = 58
Thread-1 sum = 26
main sum = 136