Java 之 应用多线程计算1+2+...+100之多种方法比较(一)
一、思路1: 不使用线程池
1.run方法
定义 static int[] arr = new int[10];
将1~100 分成10个数组,分成10个线程的run()方法分别计算
其中每个线程的run方法拿到一个ix下标当作自己的数组索引
方法1:0 -> 1~10 ; 1 -> 11~20 ; 9 -> 91~100
static void call1(int ix){ int sum = 0; // 0 -> 1~10 ; 1 -> 11~20 ; 9 -> 91~100 for (int i = ix*10+1; i <= (ix+1)*10 ; i++) { sum += i; } arr[ix] = sum; System.out.println(Thread.currentThread().getName()+"\t"+sum); }
方法2: 循环基础:i -> 0,10,20,30,40,50,60,70,80,90
i+ix: 0~90;1~91;... 9~99
i+ix+1: 1~91; 2~92;... 10~100
static void call2(int ix){ int sum = 0; // ix // 0 -> 0,10,20,30,40,50,60,70,80,90 // 1 -> 0+1=1,10+1=11,21,31 ... 91 // ... // 9 -> 9,19,29,39 ... 99 // i 从 0,10,20,30,40,50,60,70,80,90 for (int i = 0; i < 100 ; i+=10) { // sum += i+ix; // 0~90;1~91;... 9~99; sum += i+ix+1; // 1~91; 2~92;... 10~100; } arr[ix] = sum; a++; System.out.println(Thread.currentThread().getName()+"\t"+sum); }
2.可执行的 Runnable target
static class Sum implements Runnable{ // 下标ix private int ix; public Sum(int ix){ this.ix = ix; } @Override public void run() { call2(ix); // call1(ix); } }
3.mian方法测试代码
// 顺序执行,没有并发 -> 解决办法 -> 加状态值a Thread[] th = new Thread[10]; for (int i = 0; i < th.length; i++) { th[i] = new Thread(new Sum(i)); th[i].start();
th[i].join(); // Waits for this thread to die. }
int sum = 0;
for (int i = 0; i <arr.length ; i++) {
sum +=arr[i];
}
System.out.println("sum all\t"+sum);
运行结果:thread1,2,3,4,...顺序执行
优化:1)属性中增加 static int a = 0; // 状态值
2)main方法中增加状态值的判断:
二、思路2:使用线程池,不需要声明arr数组
1.run()方法:
static int _call2(int ix){ int sum = 0; for (int i = 0; i < 100 ; i+=10) { sum += i+1+ix; System.out.println(Thread.currentThread().getName()+"\t"+sum); } return sum; }
2.main方法中直接执行带返回值的submit
ExecutorService service = Executors.newFixedThreadPool(10); // 顺序执行,没有并发 for (int j = 0; j < arr.length; j++) { final int _j = j; arr[j] = service.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { // 从线程外向里面传值只能是常量 return _call2(_j); } }).get(); }
int sum = 0;
for (int i = 0; i <arr.length ; i++) {
sum +=arr[i];
}
System.out.println("sum all\t"+sum);
缺陷:一个一个把返回值塞进arr[i]中,没有并发,依然顺序
优化:1)不需要线程的get()返回值,直接放进属性中的arr[i]
2) 使用状态值a
// 线程池 + 并发 for (int j = 0; j <arr.length ; j++) { service.submit(new Sum(j)); } while (a<10){ Thread.sleep(100); } int sum = 0; for (int i = 0; i <arr.length ; i++) { sum +=arr[i]; } System.out.println("sum all\t"+sum);