Java多執行緒實現加法計算
阿新 • • 發佈:2018-12-16
採用多執行緒的方式實現從1到N的和
1.直接順序計算
public static void Sum(int N){ long start1 = System.currentTimeMillis(); long sum = 0; for(int i=1; i<=N; i++){ sum += i; } long end1 = System.currentTimeMillis(); System.out.println("序列計算耗時:" + (end1 - start1) + " ms"); System.out.println("序列計算的結果:" + sum); } public static void main(String[] args) throws ExecutionException, InterruptedException, BrokenBarrierException { //實現多執行緒加法求和 int N = 90000000; //mutilSum(arr, N, 2); Sum(N); //countDownLatchSum(N, 9); //cyclicBarrierSum2(N, 9); }
執行結果如下:
2.執行緒池和Callable
利用Callable介面可以線上程中返回結果,利用Future可以阻塞獲取結果,利用執行緒池可以批量產生多個執行緒
public static class SumThread implements Callable<Long>{ private long start; private long end; public SumThread(long start, long end){ this.start = start; this.end = end; } @Override public Long call() throws Exception { long sum = 0L; for(long i = start; i<end; i++){ sum += i; } return sum; } } //使用執行緒池+Callable介面 public static void mutilSum(int N, int numThread) throws ExecutionException, InterruptedException { ExecutorService executor = Executors.newFixedThreadPool(numThread); long start1 = System.currentTimeMillis(); List<Future<Long>> ans = new ArrayList<>(); for(int i=0; i<numThread; i++){ Future<Long> a = executor.submit( new SumThread(i*N/numThread, (i+1)*N/numThread)); ans.add(a); } long sum = 0; for (Future<Long> i : ans) { long tmp = i.get(); System.out.println("執行緒 "+i +" 的結果是: "+tmp); sum += tmp; } //平行計算 long end1 = System.currentTimeMillis(); System.out.println("平行計算耗時:" + (end1 - start1) + " ms"); System.out.println("平行計算的結果:" + sum); }
依次改變執行緒池的數量1,2,3,5,9,20,結果如下:
由測試可知,增加執行緒池得數量可以減少計算時間,然而當執行緒池數量過大時,計算效能會下降,這主要涉及到執行緒池的使用以及cpu核數與執行緒排程的關係,當執行緒數量過大時,會進行頻繁得上下文切換,導致cpu不能充分進行計算。
3.CountDownLatch
public static class SumCThread implements Runnable{ private long start; private long end; private long[] result; private CountDownLatch cdl; private int num; public SumCThread(CountDownLatch cdl, long[] result, long start, long end, int num){ this.result = result; this.start = start; this.end = end; this.cdl = cdl; this.num = num; } @Override public void run(){ long sum = 0L; for(long i=start; i<end; i++){ sum += i; } result[num] = sum; cdl.countDown(); } } //每個執行緒結果怎麼返回 執行緒如何等待最終求值 //使用CountDownLatch public static void countDownLatchSum(int N, int numThread) throws InterruptedException { long start1 = System.currentTimeMillis(); CountDownLatch cdl = new CountDownLatch(numThread); long[] result = new long[numThread]; long sum = 0L; for(int i=0; i<numThread; i++){ new Thread( new SumCThread(cdl, result,i*N/numThread, (i+1)*N/numThread, i)) .start(); } cdl.await(); for(int i=0; i<numThread; i++){ sum += result[i]; } //平行計算 long end1 = System.currentTimeMillis(); System.out.println("平行計算耗時:" + (end1 - start1) + " ms"); System.out.println("平行計算的結果:" + sum); }
依次改變執行緒池數量1,3,9
4.CyclicBarrier
使用CycleBarrier來進行執行緒同步,待所有執行緒計算完畢,在主執行緒計算中間陣列之和,求出最後結果
public static class SumCBThread implements Runnable{
private long start;
private long end;
private long[] result;
private CyclicBarrier cb;
private int num;
public SumCBThread(CyclicBarrier cb, long[] result, long start, long end,
int num){
this.result = result;
this.start = start;
this.end = end;
this.cb = cb;
this.num = num;
}
@Override
public void run(){
long sum = 0L;
for(long i=start; i<end; i++){
sum += i;
}
result[num] = sum;
try {
cb.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
//使用同步屏障來實現
public static void cyclicBarrierSum(int N, int numThread) throws
BrokenBarrierException, InterruptedException {
long start1 = System.currentTimeMillis();
CyclicBarrier cb = new CyclicBarrier(numThread+1);
long[] result = new long[numThread];
long sum = 0L;
for(int i=0; i<numThread; i++){
new Thread(
new SumCBThread(cb, result,i*N/numThread, (i+1)*N/numThread, i))
.start();
}
cb.await();
for(int i=0; i<numThread; i++){
sum += result[i];
}
//平行計算
long end1 = System.currentTimeMillis();
System.out.println("平行計算耗時:" + (end1 - start1) + " ms");
System.out.println("平行計算的結果:" + sum);
}
使用CycleBarrier構造器,傳入執行緒同步時進行操作的Runnable介面方法
public static class SumCB implements Runnable{
long[] result;
public SumCB(long[] result){
this.result = result;
}
@Override
public void run() {
long sum = 0L;
for(int i=0; i<result.length; i++){
sum += result[i];
}
System.out.println("平行計算的結果:" + sum);
}
}
public static void cyclicBarrierSum2(int N, int numThread) throws
BrokenBarrierException, InterruptedException {
long start1 = System.currentTimeMillis();
long[] result = new long[numThread];
CyclicBarrier cb = new CyclicBarrier(numThread, new SumCB(result));
for(int i=0; i<numThread; i++){
new Thread(
new SumCBThread(cb, result,i*N/numThread, (i+1)*N/numThread, i))
.start();
}
//平行計算
long end1 = System.currentTimeMillis();
System.out.println("平行計算耗時:" + (end1 - start1) + " ms");
}