synchronized如何实现两个线程交替运行?看完你就懂了,列害dei(代码片段)

author author     2022-12-26     276

关键词:

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

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

分析

主要考察线程之间的通信,思路就是创建两个线程

在一个线程输出一个内容之后,自己进入阻塞,去唤醒另一个线程

另一个线程同样,输出一个内容之后,自己进入阻塞,去唤醒另一个线程

代码实现(一)

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();

    

运行一下,确实实现了交替输出,但是多运行几次,就会发现问题

有时候是数字先输出,有时候是字母先输出

即两个线程谁先启动的顺序是不固定的

倘若试题中再加一句,必须要字母先输出,怎么办?

代码实现(二)


/**
 * 交替掩护 必须保证大写字母先输出
 */
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();

    


如此问题可以得到解决,但有更优(装)雅(B)的解决办法

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();

    


结尾

以上就是synchronized实现两个线程交替运行的解法,欢迎留言交流
感谢看到最后的朋友,都看到最后了,点个赞再走啊,如有不对之处还请多多指正。

实现两个线程从0-100交替打印(代码片段)

...去实现0-100交替打印,大家无聊的话,可以瞅两眼。一、Synchronized实现:publicclassPrintNumberIncrInSynchronizedprivatestaticintnumber;privatestaticfinalObjectobject=newObject();publicstaticvoidmain( 查看详情

wait,notify实现两个线程交替打印

...assAddPrintprivatestaticObjecto=newObject();//锁publicvoidprint(flagf)synchronized(o)for(inti=1;i<50;i++)if(f.isShouldRun())//shouldRun=false;f.setShouldRun(false);o.notify();if(i<49) 查看详情

两个线程交替打印(代码片段)

使用同一个Runnable对象加锁打印publicclassPringThreadimplementsRunnableinti=1;@Overridepublicvoidrun()while(true)synchronized(this)notify();if(i<=100)System.out.println(Thread.currentThread(). 查看详情

两个线程交替打印1到100

packagecom.zs.thread;importjava.util.concurrent.TimeUnit;publicclassSumThread{publicvoidone()throwsInterruptedException{synchronized(this){booleanflag=true;while(flag){for(inti=1;i<=99;i+=2){System 查看详情

多线程交替打印abc的多种实现方法

...;并且实现交替打印,即按照ABCABCABC的顺序打印。二、Synchronized同步法1、基本思路使用同步块和wait、notify的方法控制三个线程的执行次序。具体方法如下:从大 查看详情

两个线程交替打印数字(看了就懂版)

/***@description:*@author:*@create:2020-11-1521:12**/publicclassSwapThreadstaticclassMythread1extendsThreadpublicvoidrun()synchronized(SwapThread.class)for(inti=2;i<1000;i+=2)System.out.printl 查看详情

面试题:用程序实现两个线程交替打印0~100的奇偶数

...知识,但是面试官抛一个问题过来,短时间内可能想不出如何使用这些知识来解决这个具体的问题。其实这个问题考察的知识点并不难,但是如果准备的面试的时候没有看过这道题,一时间还是比较难想出解决方案来的,而且这... 查看详情

synchronized的底层实现原理(代码片段)

1.JDK1.6对synchronized做的优化:传统的锁(也就是下文要说的重量级锁)依赖于系统的同步函数,在linux上使用mutex互斥锁,这些同步函数都涉及到用户态和内核态的切换、进程的上下文切换,成本较高。对于加了s... 查看详情

线程交替运行

packagethreadtest;publicclassTest1{/**两个线程,一个打印1-100的奇数,一个打印1-100的偶数;要求:线程1打印5个之后,线程2开始打印,线程2打印5个之后,线程1再开始打印,以此循环。*/privatestaticintstate=1;privatestaticintnum1=1;privatestaticintn... 查看详情

请问这个java的thread程序,为啥没有出现两个线程交替运行?

publicclassThreadDemo_2publicstaticvoidmain(String[]args)TestThreadt=newTestThread();newThread(t).start();for(inti=0;i<10;i++)System.out.println("mian线程在运行!");classTestThreadimplementsRunnablepublicvoidrun()for(inti=0;i<10;i++)System.out.println("TestThread线程在... 查看详情

多线程交替打印abc的多种实现方法

...;并且实现交替打印,即按照ABCABCABC的顺序打印。二、Synchronized同步法1、基本思路使用同步块和wait、notify的方法控制三个线程的执行次序。具体方法如下:从大的方向上来讲,该问题为三线程间的同步唤醒操作,... 查看详情

synchronized同步方法的八种使用场景

...的锁,不能形成两个线程竞争一把锁的局势,所以这时,synchronized修饰的方法method()和不用synchronized修饰的效果一样(不信去把synchronized关键字去掉,运行结果一样),所以此时的method()只是个普通方法。若要使锁生效,只需将me... 查看详情

c++实现两个线程交替打印奇偶数(代码片段)

#include<iostream>#include<mutex>#include<thread>#include<condition_variable>#include<Windows.h>usingnamespacestd;mutexmut;condition_variablecond1,cond2;intg_nums=1;/ 查看详情

两个线程交替打印1-99(代码片段)

参考https://github.com/crossoverJie/JCSprout/blob/master/src/main/java/com/crossoverjie/actual/TwoThread.java从线程方面实现交替打印。publicclassTestvolatilebooleanisEven=false;@org.junit.Testpublicvoidtestfda()thr 查看详情

经典笔试题:两个线程交替打印奇偶数(代码片段)

一、采用对象的wait()notify()方法实现packagecom.gaopeng.programming;importjava.util.concurrent.TimeUnit;/***经典笔试题:交替打印奇偶数采用对象的wait()notify()方法实现**@authorgaopeng**/publicclassOddEvenThreadprivatestaticvolatileInt 查看详情

synchronized底层如何实现?啥是锁的升级,降级

参考技术Asynchronized底层如何实现?什么是锁的升级,降级。操作系统分为用户态和内核态,应用级别的程序会运行在用户态,不能访问硬件,操作系统内核的程序会运行在内核态,可以直接访问硬件。synchronized是重量级锁,运... 查看详情

阿里真题:线程交叉打印(代码片段)

...CyclicBarrier篱栅、回环屏障、Semaphore信号灯、ReentrantLock、synchronized、AtomicBoolean无锁cas。全部都已经在leetCode提交通过关于这些关键字的原理解释点我代码如下:ReentrantLock方案/***方案3Reentran 查看详情

synchronized(代码片段)

1.什么是synchronizedsynchronized 关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synch... 查看详情