java網易筆試題--線程

import java.io.*;
import java.util.*;

/**
 * 一個文件中有10000個數,用Java實現一個多線程程序將這個10000個數輸出到5個不用文件中(不要求輸出到每個文件中的數量相同)。
 * 要求啓動10個線程,兩兩一組,分爲5組。每組兩個線程分別將文件中的奇數和偶數輸出到該組對應的一個文件中,
 * 需要偶數線程每打印10個偶數以後,就將奇數線程打印10個奇數,如此交替進行。
 * 同時需要記錄輸出進度,每完成1000個數就在控制檯中打印當前完成數量,並在所有線程結束後,在控制檯打印”Done”.
 * */
public class Main{
    public static void main(String[] args){
        try{
            PrintWriter pw = new PrintWriter(new FileWriter(new File("input.txt")),true);
            Random random = new Random();
            for(int i = 0;i < 10000;i++){
                pw.print(Math.abs(random.nextInt()) % 100 + " ");
            }
            pw.flush();
            pw.close();
            BufferedReader reader = new BufferedReader(new FileReader("input.txt"));
            String str = reader.readLine();
            reader.close();
            String[] strs = str.split(" ");
            int j = 0;
            for(int i = 0;i < 5;i++){
                int[] records = new int[2000];
                for(int k = 0;k < 2000;k++){
                    records[k] = Integer.parseInt(strs[j]);
                    j++;
                }
                PrintWriter writer = new PrintWriter(new FileWriter(new File("output" + i + ".txt")),true);
                ThreadGroup group = new ThreadGroup(records,writer);
                new Thread(group).start();
                new Thread(group).start();
            }

        }catch (Exception e){
            e.printStackTrace();
        }

    }

}
class ThreadGroup implements Runnable{
    private static int count = 0;
    //所有ThreadGroup類對象共享一個鎖,用於count變量的同步,任何一個線程需要修改count變量,必須取到該鎖
    private static Object lock = new Object();
    public static final int EVEN = 0;//代表偶數
    public static final int ODD = 1;//代表奇數

    private int type;
    private int records[];
    private PrintWriter writer;
    private int oddPoint = 0;//記錄每次打印奇數的起始位置
    private int evenPoint = 0;//記錄每次打印偶數的起始位置

    public ThreadGroup(){

    }
    public ThreadGroup(int[] records,PrintWriter ps){
        this.records = records;
        this.writer = ps;
        this.type = EVEN;
    }

    @Override
    public void run() {
        while(print());
    }

    private synchronized boolean print(){
        for(int i = 0;i < 10;){
            //如果奇數和偶數都打印完成之後,就直接停止打印,等待該線程自己結束
            if(oddPoint >= records.length && evenPoint >= records.length){
                notifyAll();
                return false;
            }

            //如果該線程該打印奇數,但奇數已經打印完了就直接停滯本次10個數的打印
            //偶數同理,等下一次切換類型後再開始打印
            if((oddPoint >= records.length && type == ODD) || (evenPoint >= records.length && type == EVEN)) {
                break;
            }

            if(type == EVEN){
                if(records[evenPoint] % 2 == 0){
                    i++;
                    writer.print(records[evenPoint] + "  ");
                    writer.flush();
                    //鎖定全局變量方便線程輸出後計數
                    synchronized (lock){
                        count++;
                        if(count % 1000 == 0){
                            System.out.println("當前完成數量:" + count);
                            if(count == 10000){
                                System.out.println("Done!");
                            }
                        }
                    }
                }
                evenPoint++;
            }else{
                if(records[oddPoint] % 2 == 1){
                    i++;
                    writer.print(records[oddPoint] + " ");
                    writer.flush();
                    synchronized(lock){
                        count++;
                        if(count % 1000 == 0){
                            System.out.println("當前完成數量" + count);
                            if(count == 10000){
                                System.out.println("Done!");
                            }
                        }
                    }
                }
                oddPoint++;
            }
        }
        type = ~type;//切換打印類型
        notifyAll();    //一組中的任意線程打印完後喚醒另一個線程
        try{
            wait();     //釋放鎖進行等待狀態,等待另一線程打印完
        }catch (Exception e){
            e.printStackTrace();
        }
        return true;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章