likes
comments
collection
share

创建 n 个线程,循环打印 m 次(a-z,A-Z,大小写间隔输出)

作者站长头像
站长
· 阅读数 61
多线程面试编程题:创建n个线程,循环打印m次(a-zA-Z,大小写间隔输出)

参考链接:记一个Java多线程相关的面试题 https://www.1024sou.com/article/228174.html

例如:3个线程,打印2次(a-zA-Z) 输出结果 thread1-athread2-Athread3-b。。。。循环两次。
大概意思就是创建指定数量n的线程循环打印m次,循环内容是线程依次交错执行,分别从两个共享资源交错取数据。

这道题确实一开始写不出来,于是就遵从简单到复杂一个个写出来,然后优化升级。

本题默认使用 3 个线程来轮流打印字母,多线程轮流打印使用 Semaphore 这个并发工具类合适,因此本题使用 Semaphore 进行多线程并发控制。

最简单的解法:N 个线程打印 a-z 区间,只循环1次

public class ThreadInterleaving {

    private static final int N = 3;
    private static int count = 0;
    private static char a = 'a';
    private static Semaphore[] semaphores = new Semaphore[N];

    public static void main(String[] args) {
        try {
            new ThreadInterleaving().testAZTaskBasic();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void testAZTaskBasic() throws InterruptedException {
        for (int i = 0; i < N; i++) {
            semaphores[i] = new Semaphore(1);//只能被任意线程持有一次,释放之后才能被其他线程持有
            if (i > 0) semaphores[i].acquire();//除第0个线程对应的 Semaphore,其余都先被主线程持有
        }
        for (int i = 0; i < N; i++) {
            Semaphore cur = semaphores[i];
            Semaphore next = i == N - 1 ? semaphores[0] : semaphores[i + 1];
            new Thread(new AZTaskBasic(cur, next), "Thread" + i + ":").start();
        }
    }


    /**
     * 首先写出最简单的解法:N 个线程打印 a-z 区间,只循环1次
     * Thread0:a
     * Thread1:b
     * Thread2:c
     * Thread0:d
     * Thread1:e
     * Thread2:f
     */
    static class AZTaskBasic implements Runnable {

        private final Semaphore curSemaphore;
        private final Semaphore nextSemaphore;

        public AZTaskBasic(Semaphore curSemaphore, Semaphore nextSemaphore) {
            this.curSemaphore = curSemaphore;
            this.nextSemaphore = nextSemaphore;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    curSemaphore.acquire();
                    if (count >= 26) break;
                    System.out.println(Thread.currentThread().getName() + (char) (a + count++));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    nextSemaphore.release();
                }
            }
        }
    }
}

打印结果:

Thread0:a
Thread1:b
Thread2:c
Thread0:d
Thread1:e
Thread2:f
Thread0:g
Thread1:h
Thread2:i
Thread0:j
Thread1:k
Thread2:l
Thread0:m
Thread1:n
Thread2:o
Thread0:p
Thread1:q
Thread2:r
Thread0:s
Thread1:t
Thread2:u
Thread0:v
Thread1:w
Thread2:x
Thread0:y
Thread1:z

最简单的解法2:N 个线程打印 a-z 区间,循环2次

public class ThreadInterleaving {

    private static final int N = 3;
    private static int count = 0;
    private static char a = 'a';
    private static Semaphore[] semaphores = new Semaphore[N];

    public static void main(String[] args) {
        try {
            new ThreadInterleaving().testAZTaskBasicPrintTwice();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    private void testAZTaskBasicPrintTwice() throws InterruptedException {
        for (int i = 0; i < N; i++) {
            semaphores[i] = new Semaphore(1);
            if (i > 0) semaphores[i].acquire();
        }
        for (int i = 0; i < N; i++) {
            Semaphore cur = semaphores[i];
            Semaphore next = i == N - 1 ? semaphores[0] : semaphores[i + 1];
            new Thread(new AZTaskBasicPrintTwice(cur, next), "Thread" + i + ":").start();
        }
    }
    
    
    /**
     * 最简单的解法2:N 个线程打印 a-z 区间,循环2次
     */
    static class AZTaskBasicPrintTwice implements Runnable {

        private final Semaphore curSemaphore;
        private final Semaphore nextSemaphore;

        public AZTaskBasicPrintTwice(Semaphore curSemaphore, Semaphore nextSemaphore) {
            this.curSemaphore = curSemaphore;
            this.nextSemaphore = nextSemaphore;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    curSemaphore.acquire();
                    if (count >= 26) {
                        time++;
                        if (time >= REPEAT_TIME) break;
                        count = 0;
                    }
                    System.out.println(Thread.currentThread().getName() + (char) (a + count++));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    nextSemaphore.release();
                }
            }
        }
    }
    
    
}

打印结果:

Thread0:a
Thread1:b
Thread2:c
Thread0:d
Thread1:e
Thread2:f
Thread0:g
Thread1:h
Thread2:i
Thread0:j
Thread1:k
Thread2:l
Thread0:m
Thread1:n
Thread2:o
Thread0:p
Thread1:q
Thread2:r
Thread0:s
Thread1:t
Thread2:u
Thread0:v
Thread1:w
Thread2:x
Thread0:y
Thread1:z
Thread2:a
Thread0:b
Thread1:c
Thread2:d
Thread0:e
Thread1:f
Thread2:g
Thread0:h
Thread1:i
Thread2:j
Thread0:k
Thread1:l
Thread2:m
Thread0:n
Thread1:o
Thread2:p
Thread0:q
Thread1:r
Thread2:s
Thread0:t
Thread1:u
Thread2:v
Thread0:w
Thread1:x
Thread2:y
Thread0:z

初级:N 个线程打印 aBcDeFg..yZ 大小写间隔输出,只循环一次

public class ThreadInterleaving {

    private static final int N = 3;
    private static int count = 0;
    private static char a = 'a';
    private static Semaphore[] semaphores = new Semaphore[N];

    public static void main(String[] args) {
        try {
            new ThreadInterleaving().testAZTaskLowerHigherCase();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    private void testAZTaskLowerHigherCase() throws InterruptedException {
        for (int i = 0; i < N; i++) {
            semaphores[i] = new Semaphore(1);
            if (i > 0) semaphores[i].acquire();
        }
        for (int i = 0; i < N; i++) {
            Semaphore cur = semaphores[i];
            Semaphore next = i == N - 1 ? semaphores[0] : semaphores[i + 1];
            new Thread(new AZTaskLowerHigherCase(cur, next), "Thread" + i + ":").start();
        }
    }
    
    /**
     * 初级:N 个线程打印 aBcDeFg..yZ 大小写间隔输出,只循环一次
     */
    static class AZTaskLowerHigherCase implements Runnable {

        private final Semaphore curSemaphore;
        private final Semaphore nextSemaphore;

        public AZTaskLowerHigherCase(Semaphore curSemaphore, Semaphore nextSemaphore) {
            this.curSemaphore = curSemaphore;
            this.nextSemaphore = nextSemaphore;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    curSemaphore.acquire();
                    if (count >= 26) break;

                    if (count % 2 == 0) {
                        System.out.println(Thread.currentThread().getName() + (char) (a + count));
                    } else {
                        System.out.println(Thread.currentThread().getName() + (char) (A + count));
                    }
                    count++;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    nextSemaphore.release();
                }
            }
        }
    }
    
}

打印结果:

Thread0:a
Thread1:B
Thread2:c
Thread0:D
Thread1:e
Thread2:F
Thread0:g
Thread1:H
Thread2:i
Thread0:J
Thread1:k
Thread2:L
Thread0:m
Thread1:N
Thread2:o
Thread0:P
Thread1:q
Thread2:R
Thread0:s
Thread1:T
Thread2:u
Thread0:V
Thread1:w
Thread2:X
Thread0:y
Thread1:Z

最终解:打印 aA..zZ 大小写间隔输出, 循环2次

即:创建 n 个线程,循环打印 m 次(a-z,A-Z,大小写间隔输出)

public class ThreadInterleaving {

    private static final int N = 3;
    private static final int REPEAT_TIME = 2;
    private static int time = 0;
    private static int count = 0;
    private static final int MAX_LETTER_COUNT_PER_ROUND = 26 * 2;
    private static char A = 'A';
    private static char a = 'a';
    private static int lowerCaseIndex = 0;
    private static int higherCaseIndex = 0;
    private static Semaphore[] semaphores = new Semaphore[N];

    public static void main(String[] args) {
        try {
            new ThreadInterleaving().testAZTask();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    private void testAZTask() throws InterruptedException {
        for (int i = 0; i < N; i++) {
            semaphores[i] = new Semaphore(1);
            if (i > 0) semaphores[i].acquire();
        }
        for (int i = 0; i < N; i++) {
            Semaphore cur = semaphores[i];
            Semaphore next = i == N - 1 ? semaphores[0] : semaphores[i + 1];
            new Thread(new AZTask(cur, next), "Thread" + i + ":").start();
        }
    }
    
    /**
     * 打印 aA..zZ 大小写间隔输出, 循环2次
     */
    static class AZTask implements Runnable {

        private final Semaphore curSemaphore;
        private final Semaphore nextSemaphore;

        public AZTask(Semaphore curSemaphore, Semaphore nextSemaphore) {
            this.curSemaphore = curSemaphore;
            this.nextSemaphore = nextSemaphore;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    curSemaphore.acquire();
                    if (count >= MAX_LETTER_COUNT_PER_ROUND) {
                        time++;
                        if (time >= REPEAT_TIME) break;
                        count = 0;
                        lowerCaseIndex = 0;
                        higherCaseIndex = 0;
                    }
                    if (count % 2 == 0) {
                        System.out.println(Thread.currentThread().getName() + (char) (a + lowerCaseIndex++));
                    } else {
                        System.out.println(Thread.currentThread().getName() + (char) (A + higherCaseIndex++));
                    }
                    count++;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    nextSemaphore.release();
                }
            }
        }
    }
    
}

打印结果:

Thread0:a
Thread1:A
Thread2:b
Thread0:B
Thread1:c
Thread2:C
Thread0:d
Thread1:D
Thread2:e
Thread0:E
Thread1:f
Thread2:F
Thread0:g
Thread1:G
Thread2:h
Thread0:H
Thread1:i
Thread2:I
Thread0:j
Thread1:J
Thread2:k
Thread0:K
Thread1:l
Thread2:L
Thread0:m
Thread1:M
Thread2:n
Thread0:N
Thread1:o
Thread2:O
Thread0:p
Thread1:P
Thread2:q
Thread0:Q
Thread1:r
Thread2:R
Thread0:s
Thread1:S
Thread2:t
Thread0:T
Thread1:u
Thread2:U
Thread0:v
Thread1:V
Thread2:w
Thread0:W
Thread1:x
Thread2:X
Thread0:y
Thread1:Y
Thread2:z
Thread0:Z
Thread1:a
Thread2:A
Thread0:b
Thread1:B
Thread2:c
Thread0:C
Thread1:d
Thread2:D
Thread0:e
Thread1:E
Thread2:f
Thread0:F
Thread1:g
Thread2:G
Thread0:h
Thread1:H
Thread2:i
Thread0:I
Thread1:j
Thread2:J
Thread0:k
Thread1:K
Thread2:l
Thread0:L
Thread1:m
Thread2:M
Thread0:n
Thread1:N
Thread2:o
Thread0:O
Thread1:p
Thread2:P
Thread0:q
Thread1:Q
Thread2:r
Thread0:R
Thread1:s
Thread2:S
Thread0:t
Thread1:T
Thread2:u
Thread0:U
Thread1:v
Thread2:V
Thread0:w
Thread1:W
Thread2:x
Thread0:X
Thread1:y
Thread2:Y
Thread0:z
Thread1:Z
转载自:https://juejin.cn/post/7063423120895377422
评论
请登录