Java多線程加法計算


題意:要求開6條線程計算累加1 -> 10000000

難點:如何獲取子線程的執行結果並聚合

思路一

生產者-消費者 經典模型:

  1. 多個生產者負責生產(累加)作業
  2. 生產者將生產結果存入共享倉庫中
  3. 消費者(主線程)從共享倉庫中取出結果
/**
 * 多線程計算累加數
 */
public class Accumulate {
    public static void main(String[] args) {
        Storage storage = new Storage();
        // 為多個計算器對象創建線程
        Thread calThread1 = new Thread(new Calculate(1, storage), "Thread-1");
        Thread calThread2 = new Thread(new Calculate(2, storage), "Thread-2");
        Thread calThread3 = new Thread(new Calculate(3, storage), "Thread-3");
        Thread calThread4 = new Thread(new Calculate(4, storage), "Thread-4");
        Thread calThread5 = new Thread(new Calculate(5, storage), "Thread-5");
        Thread calThread6 = new Thread(new Calculate(6, storage), "Thread-6");

        calThread1.start();
        calThread2.start();
        calThread3.start();
        calThread4.start();
        calThread5.start();
        calThread6.start();

        // 打印最終結果
        storage.printTotal();
    }
}

/**
 * 計算器對象,負責計算start -> end
 */
class Calculate implements Runnable {
    private Storage storage;
    private long start;

    public Calculate(long start, Storage storage) {
        this.start = start;
        this.storage = storage;
    }

    @Override
    public void run() {
        long num = start;
        long sum = 0;
        while (num <= 10000000) {
            System.out.println(Thread.currentThread().getName() + " add num " + num);
            sum += num;
            num += 6;
        }
        // 線程計算完畢, 調用累加器進行累加
        storage.push(sum);
    }
}

/**
 * 倉庫對象,負責累加
 */
class Storage {
    private long total = 0;
    private int count = 0;

    public synchronized void push(long sum) {
        total += sum;
        count++;
        notifyAll();
    }

    public synchronized void printTotal() {
        while (count < 6) {
            try {
                System.out.println(Thread.currentThread().getName() + " is wait");
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("storage result = " + total);
    }
}

思路二

線程異步返回:

  1. 利用線程池並發處理多個任務
  2. 使用Future+Callable獲取異步執行結果
  3. 待線程池中所有任務結束,計算累加結果
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

/**
 * 線程池計算累加數
 */
public class Accumulate {
    public static void main(String[] args) {
        // 建立線程池 與 動態結果數組
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(6);
        List<Future<Long>> resultList = new ArrayList<>();

        // 定義10個任務分別負責一定范圍內的元素累計
        for (int i = 0; i < 10; i++) {
            CalTask calTask = new CalTask(i*100000000+1, (i+1)*100000000);
            Future<Long> result = executor.submit(calTask);
            resultList.add(result);
        }

        // 每隔50毫秒遍歷一遍所有動態結果,直到所有任務執行完畢
        do {
            System.out.printf("Main: 已經完成多少個任務: %d\n",executor.getCompletedTaskCount());
            for (int i = 0; i < resultList.size(); i++) {
                Future<Long> result = resultList.get(i);
                System.out.printf("Main: Task %d is %s\n",i,result.isDone());
            }
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        } while (executor.getCompletedTaskCount() < resultList.size());

        // 若所有任務執行完畢,則對執行結果進行累計
        long total = 0;
        for (int i = 0; i < resultList.size(); i++) {
            Future<Long> result = resultList.get(i);
            long sum = 0;
            try {
                sum = result.get();
                total += sum;
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        System.out.printf("total is: %d\n", total);
        executor.shutdown();
    }
}

class CalTask implements Callable<Long> {
    private int startNum;
    private int endNum;

    public CalTask(int startNum, int endNum) {
        this.startNum = startNum;
        this.endNum = endNum;
    }

    @Override
    public Long call() throws Exception {
        long sum = 0;
        for (int i = startNum; i <= endNum; i++) {
            sum += i;
        }
        Thread.sleep(new Random().nextInt(100));
        System.out.printf("%s: %d\n", Thread.currentThread().getName(), sum);
        return sum;
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM