面试题Java多线程循环向多个文件写入循环数字

下面是我在一次实习面试时遇到的问题,今天在看Java并发编程的艺术时突然有了更好的灵感,将原來的代码重构成了可以实现n个线程同时写入n个文件

上个版本的代码:https://blog.csdn.net/qq_37859539/article/details/85290306

有四个线程1、2、3、4。线程1的功能就是输出1,线程2的功能就是输出2,以此类推。
现在有四个文件ABCD。初始都为空。现要让四个文件呈如下格式:
A. 1 2 3 4 1 2…
B. 2 3 4 1 2 3…
C. 3 4 1 2 3 4…
D. 4 1 2 3 4 1…
请设计程序。
4个线程同时执行,每个负责向文件输出1 2 3 4
就是线程1向A B C D 四个文件输出1
就是线程2向A B C D 四个文件输出2
就是线程3向A B C D 四个文件输出3
就是线程4向A B C D 四个文件输出4
开始就是用Reentrant的一个锁对应多个condition来控制流程,但是这样是一个线程在写,3个在等没有意义
现在发现这个是有执行顺序的,注意每个IO完成的时间都不一样,注意sleep一会
线程1: A -> D -> C -> B
线程2: B -> A -> D -> C
线程3: C -> B -> A -> D
线程4: D -> C -> B -> A

import org.junit.Test;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author: wei1
 * @Date: Create in 2018/10/11 20:47
 * @Description: 
 **/
public class ThreadOrderRun6 {
    HashMap<Character, FileWriter> fwhm = new HashMap<>();
    HashMap<Character, Lock> lockhm = new HashMap<>();
    HashMap<Character, AtomicInteger> fidhm = new HashMap<>();
    HashMap<String, Condition> chm = new HashMap<>();
    CountDownLatch start = new CountDownLatch(1);

    public ThreadOrderRun6(char[] chs) throws IOException {
        //初始化创建文件A B C D
        int x = 0;
        for (char ch : chs) {
            File file = new File(ch + ".txt");
            if (file != null) {
                if (file.exists()) {
                    file.delete();
                }
                file.createNewFile();
            }
            fwhm.put(ch, new FileWriter(file));
            lockhm.put(ch, new ReentrantLock());
            if (x == 0) {
                fidhm.put(ch, new AtomicInteger(1));
                x++;
            } else {
                fidhm.put(ch, new AtomicInteger(chs.length + 1 - x));
                x++;
            }
        }
        for (char ch : chs) {
            for (int j = 1; j <= chs.length; j++) {
                chm.put("" + ch + j, lockhm.get(ch).newCondition());
            }
        }
    }


    private void firstRun() throws IOException, InterruptedException {
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName);
        String[] strs = threadName.split("_");
        char[] chs = strs[0].toCharArray();
        int i = Integer.parseInt(strs[1]) + 1;
        start.await();
        while (true) {
            for (int j = 0; j < size; j++) {
                Lock lock = lockhm.get(chs[j]);
                lock.lock();
                try {
                    while (fidhm.get(chs[j]).get() != i) {
                        chm.get("" + chs[j] + i).await();
                    }
                    fileWriter(chs[j], i + " ");

                    if (i == size) {
                        fidhm.get(chs[j]).getAndSet(1);
                    } else {
                        fidhm.get(chs[j]).getAndSet(i + 1);
                    }

//                    System.out.println("signal:" + chs[j] + fidhm.get(chs[j]).get());
                    chm.get("" + chs[j] + fidhm.get(chs[j]).get()).signal();
                } finally {
                    lock.unlock();
                }
            }
        }

    }


    private void fileWriter(char fileName, String str) throws IOException {
        fwhm.get(fileName).write(str);
        fwhm.get(fileName).flush();
    }

	//控制文件数目和写入的字母
    public static int size = 6;

    public static void main(String[] args) throws IOException {
        StringBuilder stringBuilder = new StringBuilder();
        char start = 'A';
        stringBuilder.append(start);
        for (int i = 1; i < size; i++) {
            stringBuilder.append((char) (start + size - i));
        }
        String order = stringBuilder.toString();
        ThreadOrderRun6 threadOrderRun6 = new ThreadOrderRun6(order.toCharArray());

        for (int i = 0; i < size; i++) {
            String sub1 = order.substring(0, size - i);
            String sub2 = order.substring(size - i, size);
            String threadName = sub2 + sub1 + "_" + i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        threadOrderRun6.firstRun();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }, threadName).start();
        }

        threadOrderRun6.start.countDown();
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值