一次串完大厂面试常考的多线程打印

127 阅读2分钟

下面将展示多线程交替打印的统一写法(基于线程名的),分别有synchronized和ReentranLock两种,都是阻塞式写法,以后也可以写个线程通信的写法(感兴趣的话)

A、B、C三个线程循环打印A、B、C (10次)

import java.util.concurrent.locks.ReentrantLock;

public class PrintABC {

    int times = 10;
    String name = "A";
    ReentrantLock lock = new ReentrantLock();

    // ReentrantLock实现
//    public void printABC(String s) {
//        for (int i = 0; i < times;) {
//            lock.lock();
//            try {
//                if (Thread.currentThread().getName().equals(name)) {
//                    System.out.print(s);
//                    i++;
//                    if (name.equals("A")) {
//                        name = "B";
//                    } else if (name.equals("B")) {
//                        name = "C";
//                    } else {
//                        name = "A";
//                    }
//                }
//            } finally {
//                lock.unlock();
//            }
//        }
//    }

    // synchronized实现
    public void printABC(String s) {
        for (int i = 0; i < times;) {
            synchronized (PrintABC.class) {
               if (Thread.currentThread().getName().equals(name)) {
                    System.out.print(s);
                    i++;
                    if (name.equals("A")) {
                        name = "B";
                    } else if (name.equals("B")) {
                        name = "C";
                    } else {
                        name = "A";
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        PrintABC printABC = new PrintABC();

        new Thread(() -> printABC.printABC("A"), "A").start();
        new Thread(() -> printABC.printABC("B"), "B").start();
        new Thread(() -> printABC.printABC("C"), "C").start();

    }

}

AA、BB、CC三个线程交替打印AA五次、BB十次、CC十五次,共循环10次

import java.util.concurrent.locks.ReentrantLock;

public class PrintAABBCC {
    int n = 10;  // 每个线程各执行print多少次
    String name = "AA";
    ReentrantLock lock = new ReentrantLock();

    private void print(String s, int times) {
        for (int i = 0; i < n;) {
            synchronized (PrintABC.class) {
                if (Thread.currentThread().getName().equals(name)) {
                    for (int j = 0; j < times; j++) {
                        System.out.print(s);
                    }
                    i++;
                    System.out.println();
                    if (name.equals("AA")) name = "BB";
                    else if (name.equals("BB")) name = "CC";
                    else name = "AA";
                }
            }
        }
    }

//    private void print(String s, int times) {
//        for (int i = 0; i < n;) {
//            lock.lock();
//            try {
//                if (Thread.currentThread().getName().equals(name)) {
//                    for (int j = 0; j < times; j++) {
//                        System.out.print(s);
//                    }
//                    i++;
//                    System.out.println();
//                    if (name.equals("AA")) name = "BB";
//                    else if (name.equals("BB")) name = "CC";
//                    else name = "AA";
//                }
//            } finally {
//                lock.unlock();
//            }
//        }
//    }

    public static void main(String[] args) {

        PrintAABBCC printAABBCC = new PrintAABBCC();

        new Thread(() -> printAABBCC.print("AA", 5), "AA").start();
        new Thread(() -> printAABBCC.print("BB", 10), "BB").start();
        new Thread(() -> printAABBCC.print("CC", 15), "CC").start();
    }


}

odd、even两个线程交替打印1~100

import java.util.concurrent.locks.ReentrantLock;

public class OddEvenPrint {

    int num = 50;
    int curNum = 1;
    String name = "odd";
    ReentrantLock lock = new ReentrantLock();
    

//    private void printOddEven() {
//        for (int i = 0; i < num;) {
//            synchronized (OddEvenPrint.class) {
//                if (Thread.currentThread().getName().equals(name)) {
//                    System.out.println("线程" + name + ": 打印了" + curNum);
//                    if (name.equals("odd")) {
//                        name = "even";
//                    } else {
//                        name = "odd";
//                    }
//                    curNum++;
//                    i++;
//                }
//            }
//        }
//    }

    private void printOddEven() {
        for (int i = 0; i < num;) {
            lock.lock();
            try {
                if (Thread.currentThread().getName().equals(name)) {
                    System.out.println("线程" + name + ": 打印了" + curNum);
                    if (name.equals("odd")) {
                        name = "even";
                    } else {
                        name = "odd";
                    }
                    curNum++;
                    i++;
                }
            } finally {
                lock.unlock();
            }
        }
    }


    public static void main(String[] args) {
        OddEvenPrint oddEvenPrint = new OddEvenPrint();

        new Thread(() -> oddEvenPrint.printOddEven(), "odd").start();
        new Thread(() -> oddEvenPrint.printOddEven(), "even").start();
    }

}

Num、Letter两个线程交替打印数字和字母,结果为1A2B3C...

import java.util.concurrent.locks.ReentrantLock;

public class NumAlterLetterPrint {

    int times = 26;
    String name = "Num";
    int num = 1;
    char letter = 'A';
    ReentrantLock lock = new ReentrantLock();

    private void print() {
       for (int i = 0; i < times;) {
            synchronized (NumAlterLetterPrint.class) {
                if (Thread.currentThread().getName().equals(name)) {
                    if (name.equals("Num")) {
                        System.out.print(num++);
                        name = "Letter";
                    } else {
                        System.out.print(letter++);
                        name = "Num";
                    }
                    i++;
                }
            }
        }
    }

//    private void print() {
//        for (int i = 0; i < times;) {
//            lock.lock();
//            try {
//                if (Thread.currentThread().getName().equals(name)) {
//                    if (name.equals("Num")) {
//                        System.out.print(num++);
//                        name = "Letter";
//                    } else {
//                        System.out.print(letter++);
//                        name = "Num";
//                    }
//                    i++;
//                }
//            } finally {
//                lock.unlock();
//            }
//        }
//    }



    public static void main(String[] args) {
        NumAlterLetterPrint numAlterLetterPrint = new NumAlterLetterPrint();

        new Thread(() -> numAlterLetterPrint.print(), "Num").start();
        new Thread(() -> numAlterLetterPrint.print(), "Letter").start();
    }

}

N个线程交替打印0~99(这个没用线程名作信号,毕竟麻烦)

import java.util.concurrent.locks.ReentrantLock;

public class NThreadPrint {
    int curNum = 0;  // 当前打印到那个数字了
    int times = 10;  // 每个线程要打印多少次
    static int n = 10;  // 线程的数量
    ReentrantLock lock = new ReentrantLock();


    public void print(int threadNum) {
        for (int i = 0; i < times;) {
            synchronized (NThreadPrint.class) {
                if (curNum % n == threadNum) {
                    System.out.println("线程" + threadNum + ": 打印了" + curNum++);
                    i++;
                }
            }
        }
    }

//    private void print(int threadNum) {
//        for (int i = 0; i < times;) {
//            lock.lock();
//            try {
//                if (curNum % n == threadNum) {
//                    System.out.println("线程" + threadNum + ": 打印了" + curNum++);
//                    i++;
//                }
//            } finally {
//                lock.unlock();
//            }
//        }
//    }

    public static void main(String[] args) {
        NThreadPrint nThreadPrint = new NThreadPrint();

        for (int i = 0; i < n; i++) {
            int finalI = i;
            new Thread(() -> nThreadPrint.print(finalI)).start();
        }

    }
}