3個(gè)線(xiàn)程循環(huán)打印到不同文件

最近在面試阿里的,遇到一個(gè)筆試題献幔,題目是這樣的:

多線(xiàn)程寫(xiě)文件懂傀,有3個(gè)線(xiàn)程1、2蜡感、3蹬蚁。線(xiàn)程1的功能就是輸出t1,線(xiàn)程2的功能就是輸出t2郑兴,以此類(lèi)推.........犀斋,
 現(xiàn)在有三個(gè)文件file1,file2,file3。初始都為空情连,現(xiàn)要讓三個(gè)文件呈如下格式:
 file1:t1 t2 t3 t1 t2....
 file2:t2 t3 t1 t2 t3....
 file3:t3 t1 t2 t3 t1….

下面以2中方式完成這題

第一種采用ReentranLock+condition進(jìn)行實(shí)現(xiàn)叽粹,具體代碼如下:

package thread;

import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 多線(xiàn)程寫(xiě)文件,有3個(gè)線(xiàn)程1却舀、2虫几、3。線(xiàn)程1的功能就是輸出t1挽拔,線(xiàn)程2的功能就是輸出t2辆脸,以此類(lèi)推.........,
 * 現(xiàn)在有三個(gè)文件file1,file2,file3螃诅。初始都為空啡氢,現(xiàn)要讓三個(gè)文件呈如下格式:
 * file1:t1 t2 t3 t1 t2....
 * file2:t2 t3 t1 t2 t3....
 * file3:t3 t1 t2 t3 t1….
 *
 * @Author: huangyichun
 * @Date: 2021/3/14
 */
public class CircleFileWriter {


    public CircleFileWriter() throws IOException {
    }

    public static void main(String[] args) throws InterruptedException, IOException {
        CircleFileWriter fileWriter = new CircleFileWriter();
        Thread thread1 = new Thread(fileWriter::printT1);
        Thread thread2 = new Thread(fileWriter::printT2);
        Thread thread3 = new Thread(fileWriter::printT3);

        thread1.start();
        Thread.sleep(100);
        thread2.start();
        Thread.sleep(100);
        thread3.start();
    }

    FileWriter fileWriter1 = new FileWriter("file1");
    FileWriter fileWriter2 = new FileWriter("file2");
    FileWriter fileWriter3 = new FileWriter("file3");

    //當(dāng)前循環(huán)的圈數(shù),用于判斷當(dāng)前線(xiàn)程輸出的文件
    private volatile int loop = 0;

    private final ReentrantLock lock = new ReentrantLock();
    Condition condition1 = lock.newCondition();
    Condition condition2 = lock.newCondition();
    Condition condition3 = lock.newCondition();

    private final int times = 100;

    public void printT1() {
        lock.lock();
        try {
            print(1, condition1, condition2, "t1");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printT2() {
        lock.lock();
        try {
           print(2, condition2, condition3, "t2");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printT3() {
        lock.lock();
        try {
            print(3, condition3, condition1, "t3");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    
     /**
     * 實(shí)際打印方法
     * @param threadNumber 當(dāng)前線(xiàn)程id 對(duì)應(yīng)1术裸,2倘是,3
     * @param current 控制當(dāng)前線(xiàn)程的condition
     * @param next 控制后一個(gè)線(xiàn)程的condition
     * @param str 打印的內(nèi)容
     * @throws InterruptedException
     */
    private void print(int threadNumber, Condition current, Condition next, String str) throws InterruptedException {
        for (int i = 0; i < 100; i++) {//打印100次
            writeFile(getFile(threadNumber, loop), str);
            if (threadNumber == 3) {
                loop++;
            }
            next.signal();
            if (i < times - 1) { //最后一次不需要等待
                current.await();
            }
        }
    }

    /**
     * 寫(xiě)入文件
     **/
    private void writeFile(FileWriter fw, String s) {
        System.out.println(Thread.currentThread().getName() + "打印:" + s + "到");
        try {
            fw.append(s);
            fw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 判斷在當(dāng)前線(xiàn)程在第loop循環(huán)情況下寫(xiě)入哪個(gè)文件
     **/
    private FileWriter getFile(int threadNumber, int loop) {

        if (threadNumber == 1) {
            if (loop % 3 == 0) {
                return fileWriter1;
            } else if (loop % 3 == 1) {
                return fileWriter3;
            } else {
                return fileWriter2;
            }
        } else if (threadNumber == 2) {
            if (loop % 3 == 0) {
                return fileWriter2;
            } else if (loop % 3 == 1) {
                return fileWriter1;
            } else {
                return fileWriter3;
            }
        } else {
            if (loop % 3 == 0) {
                return fileWriter3;
            } else if (loop % 3 == 1) {
                return fileWriter2;
            } else {
                return fileWriter1;
            }
        }
    }
}

第二種方法,不是用鎖穗椅,使用volatile進(jìn)行控制線(xiàn)程循環(huán)打印辨绊。

package thread;

import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 多線(xiàn)程寫(xiě)文件,有3個(gè)線(xiàn)程1匹表、2门坷、3宣鄙。線(xiàn)程1的功能就是輸出t1,線(xiàn)程2的功能就是輸出t2默蚌,以此類(lèi)推.........冻晤,
 * 現(xiàn)在有三個(gè)文件file1,file2,file3。初始都為空绸吸,現(xiàn)要讓三個(gè)文件呈如下格式:
 * file1:t1 t2 t3 t1 t2....
 * file2:t2 t3 t1 t2 t3....
 * file3:t3 t1 t2 t3 t1….
 *
 * @Author: huangyichun
 * @Date: 2021/3/14
 */
public class CircleFileWriter2 {


    public CircleFileWriter2() throws IOException {
    }

    public static void main(String[] args) throws InterruptedException, IOException {
        CircleFileWriter2 fileWriter = new CircleFileWriter2();
        Thread thread1 = new Thread(fileWriter::printT1);
        Thread thread2 = new Thread(fileWriter::printT2);
        Thread thread3 = new Thread(fileWriter::printT3);

        thread1.start();
        Thread.sleep(100);
        thread2.start();
        Thread.sleep(100);
        thread3.start();
    }

    FileWriter fileWriter1 = new FileWriter("file1");
    FileWriter fileWriter2 = new FileWriter("file2");
    FileWriter fileWriter3 = new FileWriter("file3");

    private volatile int loop = 0;

    private volatile int state = 0;

    public void printT1() {
        print(1, "t1");

    }

    public void printT2() {
        print(2, "t2");

    }

    public void printT3() {
        print(3, "t3");

    }

    private void print(int threadNumber, String str) {

        for (int i = 0; i < 100; i++) {//打印100次
            while (true) {
                if ((state % 3) + 1 == threadNumber) {
                    writeFile(getFile(threadNumber, loop), str);
                    if (threadNumber == 2) {
                        loop++;
                    }
                    state ++;
                    break;
                }
            }
        }
    }

    /**
     * 寫(xiě)入文件
     **/
    private void writeFile(FileWriter fw, String s) {
        try {
            fw.append(s);
            fw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 判斷在當(dāng)前線(xiàn)程在第loop循環(huán)情況下寫(xiě)入哪個(gè)文件
     **/
    private FileWriter getFile(int threadNumber, int loop) {

        if (threadNumber == 1) {
            if (loop % 3 == 0) {
                return fileWriter1;
            } else if (loop % 3 == 1) {
                return fileWriter3;
            } else {
                return fileWriter2;
            }
        } else if (threadNumber == 2) {
            if (loop % 3 == 0) {
                return fileWriter2;
            } else if (loop % 3 == 1) {
                return fileWriter1;
            } else {
                return fileWriter3;
            }
        } else {
            if (loop % 3 == 0) {
                return fileWriter3;
            } else if (loop % 3 == 1) {
                return fileWriter2;
            } else {
                return fileWriter1;
            }
        }
    }
}

兩種方法都能實(shí)現(xiàn)循環(huán)打印鼻弧,但是第二種方式?jīng)]有加鎖,對(duì)cpu的消耗較大锦茁,而且性能不高攘轩,執(zhí)行時(shí)間也耗時(shí)較長(zhǎng)。在打印100萬(wàn)的數(shù)據(jù)中码俩,第一種方法耗時(shí) 8431ms度帮, 第二種方法耗時(shí) 14406ms。所以面試時(shí)建議寫(xiě)第一種稿存,第二種僅作參考笨篷。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市瓣履,隨后出現(xiàn)的幾起案子率翅,更是在濱河造成了極大的恐慌,老刑警劉巖袖迎,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冕臭,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡瓢棒,警方通過(guò)查閱死者的電腦和手機(jī)浴韭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)脯宿,“玉大人念颈,你說(shuō)我怎么就攤上這事×梗” “怎么了榴芳?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)跺撼。 經(jīng)常有香客問(wèn)我窟感,道長(zhǎng),這世上最難降的妖魔是什么歉井? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任柿祈,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘躏嚎。我一直安慰自己蜜自,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布卢佣。 她就那樣靜靜地躺著重荠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪虚茶。 梳的紋絲不亂的頭發(fā)上戈鲁,一...
    開(kāi)封第一講書(shū)人閱讀 52,156評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音嘹叫,去河邊找鬼婆殿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛待笑,可吹牛的內(nèi)容都是我干的鸣皂。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼暮蹂,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了癌压?” 一聲冷哼從身側(cè)響起仰泻,我...
    開(kāi)封第一講書(shū)人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎滩届,沒(méi)想到半個(gè)月后集侯,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡帜消,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年棠枉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泡挺。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡辈讶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出娄猫,到底是詐尸還是另有隱情贱除,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布媳溺,位于F島的核電站月幌,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏悬蔽。R本人自食惡果不足惜扯躺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧录语,春花似錦倍啥、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至失暂,卻和暖如春彼宠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背弟塞。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工凭峡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人决记。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓摧冀,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親系宫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子索昂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容