Java交替打印顺序1~100,5种线程间通讯技巧你得掌握

本人第一篇CSDN博客,哈哈哈,笔者来自于世界500强企业,先后在诺基亚,通用等大企业做过N多java后端项目核心开发,也积累了大量的开发经验,扯远了,关注文章标题,其实,这种面试题就是考察的Java多线程间通讯技术,其实在Java中,能够完成线程间的技术很多,本文列举5中方法,其他的方法请自行探索。

 

1.基于volatile变量规则

在java中,volatile可以保证变量的可见性和禁止指令重排(基于内存屏障),理解了这一点也就不难实现了。看代码:

/**
 * 基于Volatile变量
 */
public class Test5 {
    static volatile boolean FLAG = false;
    static volatile int num = 1;

    public static void main(String[] args) {
        new Thread(() -> {
            while (true) {
                if (num < 101 && !FLAG) {
                    System.out.printf("线程Id:%s,打印的数字:%s \n", Thread.currentThread().getId(), num++);
                    FLAG = true;
                }
            }
        }).start();

        new Thread(() -> {
            while (true) {
                if (num < 101 && FLAG) {
                    System.out.printf("线程Id:%s,打印的数字:%s \n", Thread.currentThread().getId(), num++);
                    FLAG = false;
                }
            }
        }).start();
    }
}

结果:

线程Id:9,打印的数字:1 
线程Id:10,打印的数字:2 
线程Id:9,打印的数字:3 
线程Id:10,打印的数字:4 

.....

2.基于同步锁

也就是基于sychoronized同步块实现,同步锁基于语义为管程锁隐式实现的,重要两个命令monitor enter,monitor exit,

一旦方法或者代码块有同步锁标识,即当前线程自动进入monitor的entry_list等待获取锁,一旦获取到锁,则会进入临界区继续运行,假如此时调用了持有当前锁对象的wait()方法,当前线程会主动释放锁,并让出CPU资源,并进入monitor的wait_set等待唤醒。

/**
 * 基于同步锁,即obj的wait()和notify方法
 */
public class Test {
    static volatile int num = 1;
    static Object obj = new Object();
    public static void main(String[] args) {
        new Thread(() -> {
            while (num < 101) {
                synchronized (obj) {
                    try {
                        obj.wait();
                        System.out.printf("线程Id:%s,打印的数字:%s \n", Thread.currentThread().getId(), num++);
                        obj.notify();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        new Thread(() -> {
            while (num < 101) {
                synchronized (obj) {
                    try {
                        System.out.printf("线程Id:%s,打印的数字:%s \n", Thread.currentThread().getId(), num++);
                        obj.notify();
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}

 

3.基于重入锁

/**
 * 基于重入锁
 */
public class Test2 {
    static ReentrantLock reentrantLock = new ReentrantLock();
    static Condition thread1Condition = reentrantLock.newCondition();
    static Condition thread2Condition = reentrantLock.newCondition();
    static volatile int num = 1;
    public static void main(String[] args) {
        new Thread(() -> {
            while (num < 100) {
                reentrantLock.lock();
                try {
                    thread1Condition.await();
                    System.out.printf("线程Id:%s,打印的数字:%s \n", Thread.currentThread().getId(), num++);
                    thread2Condition.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    if (reentrantLock.isHeldByCurrentThread()) {
                        reentrantLock.unlock();
                    }
                }
            }
        }).start();
        new Thread(() -> {
            while (num < 100) {
                reentrantLock.lock();
                try {
                    System.out.printf("线程Id:%s,打印的数字:%s \n", Thread.currentThread().getId(), num++);
                    thread1Condition.signal();
                    thread2Condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    if (reentrantLock.isHeldByCurrentThread()) {
                        reentrantLock.unlock();
                    }
                }
            }
        }).start();
    }
}

4.基于信号量

/**
 * 基于信号量
 */
public class Test3 {

    static Semaphore thread1=new Semaphore(1);
    static Semaphore thread2=new Semaphore(0);
    static volatile int num=1;

    public static void main(String[] args) {
        new Thread(()->{
            while (num<100){
                try {
                    thread2.acquire();
                    System.out.printf("线程Id:%s,打印的数字:%s \n", Thread.currentThread().getId(), num++);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    thread1.release();
                }
            }
        }).start();

        new Thread(()->{
            while (num<100){
                try {
                    thread1.acquire();
                    System.out.printf("线程Id:%s,打印的数字:%s \n", Thread.currentThread().getId(), num++);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    thread2.release();
                }
            }
        }).start();
    }

}

5.基于LockSupport

/**
 * 基于LockSupport
 */
public class Test4 {

    private static volatile int num = 1;

    public static void main(String[] args) {
        Thread main=Thread.currentThread();

        Thread thread1 = new Thread(() -> {
            while (num < 101) {
                LockSupport.park();
                System.out.printf("线程Id:%s,打印的数字:%s \n", Thread.currentThread().getId(), num++);
                LockSupport.unpark(main);
            }
        });
        thread1.start();

        while (num<101){
            System.out.printf("线程Id:%s,打印的数字:%s \n", Thread.currentThread().getId(), num++);
            LockSupport.unpark(thread1);
            LockSupport.park();
        }
    }

}

6.简单sleep()方法

之所以不太想提这种方法,主要是觉得这有点背离面试官的初衷,再一点我们在正常的生产环境是不能这样写的,哈哈哈,否则要被拉出去批斗,既然作为博客,我觉得应该集思广益,但万万不可用于生产环境的业务代码,自己玩玩可以。

 

/**
 * 简单sleep
 */
public class Test6 {

    static volatile int num=1;

    public static void main(String[] args) {
        new Thread(()->{
            while (num<101){
                try {
                    System.out.printf("线程Id:%s,打印的数字:%s \n", Thread.currentThread().getId(), num++);
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        new Thread(()->{
            while (num<101){
                try {
                    System.out.printf("线程Id:%s,打印的数字:%s \n", Thread.currentThread().getId(), num++);
                    Thread.sleep(201);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

 

好啦,废话不多说,能让你们有所收获就好。

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值