Como o synchronized percebe que dois threads são executados alternadamente? Você entenderá depois de ler isso, liste o dano dei

fundo

用两个线程交替输出A-Z和1-26,即一个线程输出A-Z,另一个线程输出1-26
而且是交替形式

线程1输出A——线程二输出1
线程1输出B——线程二输出2
线程1输出C——线程二输出3
以此类推

análise

Examinar principalmente a comunicação entre threads, a ideia é criar dois threads

Depois que um thread gera um conteúdo, ele entra no bloqueio por si mesmo para ativar outro thread

Da mesma forma, outro encadeamento, depois de enviar um conteúdo, entra no bloco sozinho para despertar outro encadeamento

Implementação de código (1)

public class AlternateCover {

    public static void main(String[] args) {

        final char[] arrLetter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
        final String[] arrNumber = {"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26"};

        threadRun(arrLetter, arrNumber);
    }

    private static void threadRun(char[] arrLetter,String[] arrNumber){

        final Object lock = new Object();// 设置一个锁对象

        // print arrNumber
        new Thread(() -> {
            synchronized (lock) {
                for (String a : arrNumber) {
                    System.out.print( a);
                    try {
                        lock.notify();// 唤醒其他等待的线程 此处唤醒 arrLetter
                        lock.wait();// arrNumber自己进入等待 让出CPU资源和锁资源
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                lock.notify();
            }
        }, "arrNumber ").start();

        // print arrLetter
        new Thread(() -> {
            synchronized (lock) {// 获取对象锁
                for (char a : arrLetter) {
                    System.out.print(a);
                    try {
                        lock.notify();// 唤醒其他等待的线程 此处唤醒 arrNumber
                        lock.wait();// arrLetter自己进入等待 让出CPU资源和锁资源
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                lock.notify();// 最后那个等待的线程需要被唤醒,否则程序无法结束
            }
        }, "arrLetter ").start();

    }
}

Execute-o, ele obtém uma saída alternativa, mas se você executá-lo várias vezes, encontrará o problema

Às vezes, os números são impressos primeiro, às vezes as letras são impressas primeiro

Ou seja, a ordem em que os dois threads começam primeiro não é fixa

O que devo fazer se adicionar outra frase à pergunta do teste e as letras tiverem que ser impressas primeiro?

Implementação de código (dois)


/**
 * 交替掩护 必须保证大写字母先输出
 */
public class AlternateCover {

    public static volatile Boolean  flg = false;// 谁先开始的标志 volatile修饰目的是让该值修改对所有线程可见,且防止指令重排序
    public static void main(String[] args) {

        final char[] arrLetter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
        final String[] arrNumber = {"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26"};

        threadRun(arrLetter, arrNumber);
    }

    private static void threadRun(char[] arrLetter,String[] arrNumber){

        final Object lock = new Object();// 锁对象

        // print arrLetter
        new Thread(() -> {
            synchronized (lock) {
                if (!flg){ // 如果flg是false 就将值设为true
                    flg = true;
                }
                for (char a : arrLetter) {
                    System.out.print(a);// 输出内容
                    try {
                        lock.notify();// 唤醒在等待的其他线程中的一个(此处也只有另一个)
                        lock.wait();// 自己进入等待 让出CPU资源和锁资源
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                lock.notify();// 最后那个等待的线程需要被唤醒,否则程序无法结束
            }
        }, "arrLetter").start();

        // print arrNumber
        new Thread(() -> {
            synchronized (lock) {
                if (!flg){// 倘若是该线程先执行,那么flg次数还是false 就先等着
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                for (String a : arrNumber) {
                    System.out.print( a);
                    try {
                        lock.notify();
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                lock.notify();
            }
        }, "arrNumber").start();

    }

}

Este problema pode ser resolvido, mas existe uma solução melhor (instalada) elegante (B)

Implementação de CountDownLatch

/**
 * 交替掩护 必须保证大写字母先输出
 */
public class AlternateCover {

    private static CountDownLatch count = new CountDownLatch(1);// 计数器容量为1
    public static void main(String[] args) {

        final char[] arrLetter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
        final String[] arrNumber = {"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26"};

        threadRun(arrLetter, arrNumber);
    }

    private static void threadRun(char[] arrLetter,String[] arrNumber){

        final Object lock = new Object();

        // print arrLetter
        new Thread(() -> {
            synchronized (lock) {// 获取对象锁
                count.countDown();// 对计数器进行递减1操作,当计数器递减至0时,当前线程会去唤醒阻塞队列里的所有线程(只针对count)
                for (char a : arrLetter) {
                    System.out.print(a);
                    try {
                        lock.notify();// 唤醒其他等待的线程 此处唤醒 arrNumber
                        lock.wait();// arrLetter自己进入等待 让出CPU资源和锁资源
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                lock.notify();// 最后那个等待的线程需要被唤醒,否则程序无法结束
            }
        }, "arrLetter ").start();

        // print arrNumber
        new Thread(() -> {
            synchronized (lock) {
                try {
                    count.await();// 如果该线程先执行 阻塞当前线程,将当前线程加入阻塞队列
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                for (String a : arrNumber) {
                    System.out.print( a);
                    try {
                        lock.notify();// 唤醒其他等待的线程 此处唤醒 arrLetter
                        lock.wait();// arrNumber自己进入等待 让出CPU资源和锁资源
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                lock.notify();
            }
        }, "arrNumber ").start();

    }

}

fim

O acima é a solução de sincronizado para conseguir dois threads em execução alternadamente. Bem-vindo a deixar uma mensagem e trocar.
Obrigado por ver os últimos amigos. Todos eles são vistos no final. Dê um joinha antes de sair. Corrija-me se houver algo errado.

Acho que você gosta

Origin blog.51cto.com/14969174/2545024
Recomendado
Clasificación