线程打印_阿里面试题:怎么控制多线程的打印顺序?

3209f0879f3f5b06963e5dc45cd28635.png

面试题:

编写一个程序,开启三个线程A,B,C , 这三个线程输出分别为 A、B、C,要求,按顺序输出ABC,循环10次, 分别为 ABCABCABCABCABC......

下面介绍以下四种实现方式

2.1 用synchronized、wait、notifyAll实现

标准的实现模式如下

1、等待方遵循如下原则。

(1) 获取对象的锁。

(2) 如果条件不满足,那么调用对象的wait()方法,被通知后仍要检查条件。

(3) 条件满足则执行对应的逻辑。

synchronized(对象){
    while(条件不满足){
      对象.wait();
    }
     对应的处理逻辑;
}

2、通知方遵循如下原则。

(1) 获得对象的锁。

(2)改变条件。

(3) 通知所有等待在对象上的线程。

synchronized (对象){
    改变条件;
    对象.notifyAll();
}

实现代码如下:

27a2f39f44786def369f5414c797681e.png

df04aebee9381817c7fe6d542352d8cb.png

测试结果:

e5c579e6c31e7becb41cbee4ca7465b4.png

实现步骤如下:

1、线程定义每个线程执行的次数

2、A B C 三个线程都需要先获取锁,无论谁先获取线程执行的优先权,Index 最初值为1,如果B 或者 C 先拿到执行权,则判断后,都会释放锁。最终会A拿到执行权。

3、A执行后正好对index 取模 等于1,然后执行,唤醒B和C线程去执行

4、B 和 C线程拿到执行权后,判断完成后,最终还是B得到执行

5、依次循环下去

2.2 用 ReentrantLock 和 Condition

ReentrantLock 是可重入锁,支持公平和非公平锁。

Condition 条件变量,对于每一个Lock,可以由任意数量的Condition对象,

因此对于不同的条件谓词,对于同一锁,可以用不同的Condition 对象老控制。

Condition 对象会继承相关的Lock公平性,对于公平的锁,线程会一招FIFO 顺序从await中释放。

标准的写法如下:

e11525eec323d6343650547aebdbcda0.png

实现代码如下:

5123db1a45424b07830c0c4965b48e97.png

762c7c7d14ed4897a5baa5526e0b4964.png

e09ee8b70c890e8a981b7e261dd7361f.png

测试结果:

63d702aa3d481387c5ad59163be362bb.png

2.3 用 ReentrantLock 和 多个Condition

Condition 能够更加精细的控制多线程的等待和唤醒,并且对于通过一个锁可以创建多个Condition监视器。

利用不同的Condition对象实现当一个线程结束,唤醒下一个线程。

使用volatile 修饰index, 可以在线程之间保持可见性。

实现代码如下:

b6eae7d346636fde210d3e12e4fba7cc.png

4b456f7e2213a9f7601bd0d0917baa7a.png

结果:

80107398a18fbca0e9d31222d8d8e144.png

实现步骤:

1、首先定义一个index区别每个线程。

2、首先 A,B ,C 三个线程同时抢执行权,A的条件是index == 0,B 的条件是 index == 1,

C的条件是 index == 1.

3、满足条件后,依次进行唤醒。

2.4 用 Semaphore 计数器

Semaphore 是一个计数器信号量,必须由获取它的线程释放,通常用于限制可以访问某些资源。

Semaphore方法如下:

  1. acquire: 方法阻塞,直到有一个许可证可以获取然后拿走一个租客正
  2. release: 增加一个许可证,然后释放一个阻塞acquire的方法

下面用生活场景介绍

比如××马路要限制流量,只允许同时有一百辆车在这条路上行驶,其他的都必须

在路口等待,所以前一百辆车会看到绿灯,可以开进这条马路,后面的车会看到红灯,不能驶

入××马路,但是如果前一百辆中有5辆车已经离开了××马路,那么后面就允许有5辆车驶入马

路,这个例子里说的车就是线程,驶入马路就表示线程在执行,离开马路就表示线程执行完

成,看见红灯就表示线程被阻塞,不能执行。

实现代码如下:

f6e1b3e1439ec5d05217d8dd185815f1.png

a6bbe7c84b0a3b9d6ba5410e3d526d38.png

结果为:

79a06c8cb557f28df9621c949b22e97d.png

实现原理:

1、首先让A有一个许可证,B C 默认为0个

2、如果B或者C获取执行权,由于没有许可证,线程执行权会到A手中。

3、A 执行后,由于有许可证,所以代码可以执行下去。执行完成后,增加B的许可证。

4、B执行,执行完后,增加C的许可证,C执行完成后,增加A的许可证,A线程再次执行。

如果你有不同的见解,欢迎评论!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值