在面试题中,我们经常会遇到这样的题目,线程依次交替执行,比如有三个线程,第一个线程打印1-2-3,第二个线程接着打印4-5-6,第三个线程打印7-8-9,再更换到线程一运行打印10-11-12,依此类推。或者只有两个线程,他们直接交替执行。
我们知道,默认情况下,多线程运行,资源是共享的,也就是说他们是竞争关系,谁得到cpu资源,谁就运行,其他线程等待,当运行完毕,接下来由谁运行,是不确定的,有可能还是刚才抢占过cpu资源的线程执行。
按照一些面试题的要求,我们需要资源按顺序分配,或者公平分配,而不是去争抢。如果是两个线程,可以考虑使用公平锁,这个很好解决,看代码:
package com.xxx.lock;
import java.util.concurrent.locks.ReentrantLock;
public class FairLockDemo {
public static void main(String[] args) {
Runnable target = new Runnable(){
private ReentrantLock lock = new ReentrantLock(true);
@Override
public void run() {
int i=10;
while (i>0) {
try{
lock.lock();
System.out.println(Thread.currentThread().getName()+"get lock.for loop "+i);
}finally{
lock.unlock();
}
i--;
}
}
};
Thread t1 = new Thread(target, "thread-1");
Thread t2 = new Thread(target, "thread-2");
t1.start();
t2.start();
}
}
运行结果:
thread-1 get lock.for loop 10
thread-2 get lock.for loop 10
thread-1 get lock.for loop 9
thread-2 get lock.for loop 9
thread-1 get lock.for loop 8
thread-2 get lock.for loop 8
thread-1 get lock.for loop 7
thread-2 get lock.for loop 7
thread-1 get lock.for loop 6
thread-2 get lock.for loop 6
thread-1 get lock.for loop 5
thread-2 get lock.for loop 5
thread-1 get lock.for loop 4
thread-2 get lock.for loop 4
thread-1 get lock.for loop 3
thread-2 get lock.for loop 3
thread-1 get lock.for loop 2
thread-2 get lock.for loop 2
thread-1 get lock.for loop 1
thread-2 get lock.for loop 1
代码中用到的公平锁是通过类ReentrantLock来构建的,他默认可以不带参数,如果带了参数true,那么就是一个公平锁。我们看这个类的描述信息:

如果有三个或者三个以上的线程需要依次执行,那么这个公平锁就不合适了,他的效果比没有使用公平锁会好一点,就是任何线程不会一直抢占执行,但是无法保证线程依次按顺序执行。
这里需要用到锁的Condition机制,利用Condition能够帮助我们完成三个或者三个以上的线程依次顺序执行,看代码:下面是一个主线程和两个子线程,他们分别按照顺序执行:
package com.xxx.lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionTest {
public static void main(String[] args) {
new ConditionTest().init();
}
public void init(){
final Business bus = new Business();
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<10;i++){
bus.sub2(i);
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<10;i++){
bus.sub3(i);
}
}
}).start();
for(int i=0;i<10;i++){
bus.sub1(i);
}
}
}
class Business{
private int flag = 1;
Lock lock = new ReentrantLock();
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
Condition c3 = lock.newCondition();
public void sub1(int n){
lock.lock();
try{
while(flag!=1){
try {
c1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int i=0;i<3;i++){
System.out.println("sub1 thread sequence of " +i+",loop of "+n);
}
flag = 2;
c2.signal();
}finally{
lock.unlock();
}
}
public void sub2(int n){
lock.lock();
try{
while(flag!=2){
try {
c2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int i=0;i<3;i++){
System.out.println("sub2 thread sequence of " +i+",loop of "+n);
}
flag = 3;
c3.signal();
}finally{
lock.unlock();
}
}
public void sub3(int n){
lock.lock();
try{
while(flag!=3){
try {
c3.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int i=0;i<3;i++){
System.out.println("sub3 thread sequence of " +i+",loop of "+n);
}
flag = 1;
c1.signal();
}finally{
lock.unlock();
}
}
}
程序运行打印结果:
sub1 thread sequence of 0,loop of 0
sub1 thread sequence of 1,loop of 0
sub1 thread sequence of 2,loop of 0
sub2 thread sequence of 0,loop of 0
sub2 thread sequence of 1,loop of 0
sub2 thread sequence of 2,loop of 0
sub3 thread sequence of 0,loop of 0
sub3 thread sequence of 1,loop of 0
sub3 thread sequence of 2,loop of 0
sub1 thread sequence of 0,loop of 1
sub1 thread sequence of 1,loop of 1
sub1 thread sequence of 2,loop of 1
sub2 thread sequence of 0,loop of 1
sub2 thread sequence of 1,loop of 1
sub2 thread sequence of 2,loop of 1
sub3 thread sequence of 0,loop of 1
sub3 thread sequence of 1,loop of 1
sub3 thread sequence of 2,loop of 1
sub1 thread sequence of 0,loop of 2
sub1 thread sequence of 1,loop of 2
sub1 thread sequence of 2,loop of 2
sub2 thread sequence of 0,loop of 2
sub2 thread sequence of 1,loop of 2
sub2 thread sequence of 2,loop of 2
sub3 thread sequence of 0,loop of 2
sub3 thread sequence of 1,loop of 2
sub3 thread sequence of 2,loop of 2
sub1 thread sequence of 0,loop of 3
sub1 thread sequence of 1,loop of 3
sub1 thread sequence of 2,loop of 3
sub2 thread sequence of 0,loop of 3
sub2 thread sequence of 1,loop of 3
sub2 thread sequence of 2,loop of 3
sub3 thread sequence of 0,loop of 3
sub3 thread sequence of 1,loop of 3
sub3 thread sequence of 2,loop of 3
sub1 thread sequence of 0,loop of 4
sub1 thread sequence of 1,loop of 4
sub1 thread sequence of 2,loop of 4
sub2 thread sequence of 0,loop of 4
sub2 thread sequence of 1,loop of 4
sub2 thread sequence of 2,loop of 4
sub3 thread sequence of 0,loop of 4
sub3 thread sequence of 1,loop of 4
sub3 thread sequence of 2,loop of 4
sub1 thread sequence of 0,loop of 5
sub1 thread sequence of 1,loop of 5
sub1 thread sequence of 2,loop of 5
sub2 thread sequence of 0,loop of 5
sub2 thread sequence of 1,loop of 5
sub2 thread sequence of 2,loop of 5
sub3 thread sequence of 0,loop of 5
sub3 thread sequence of 1,loop of 5
sub3 thread sequence of 2,loop of 5
sub1 thread sequence of 0,loop of 6
sub1 thread sequence of 1,loop of 6
sub1 thread sequence of 2,loop of 6
sub2 thread sequence of 0,loop of 6
sub2 thread sequence of 1,loop of 6
sub2 thread sequence of 2,loop of 6
sub3 thread sequence of 0,loop of 6
sub3 thread sequence of 1,loop of 6
sub3 thread sequence of 2,loop of 6
sub1 thread sequence of 0,loop of 7
sub1 thread sequence of 1,loop of 7
sub1 thread sequence of 2,loop of 7
sub2 thread sequence of 0,loop of 7
sub2 thread sequence of 1,loop of 7
sub2 thread sequence of 2,loop of 7
sub3 thread sequence of 0,loop of 7
sub3 thread sequence of 1,loop of 7
sub3 thread sequence of 2,loop of 7
sub1 thread sequence of 0,loop of 8
sub1 thread sequence of 1,loop of 8
sub1 thread sequence of 2,loop of 8
sub2 thread sequence of 0,loop of 8
sub2 thread sequence of 1,loop of 8
sub2 thread sequence of 2,loop of 8
sub3 thread sequence of 0,loop of 8
sub3 thread sequence of 1,loop of 8
sub3 thread sequence of 2,loop of 8
sub1 thread sequence of 0,loop of 9
sub1 thread sequence of 1,loop of 9
sub1 thread sequence of 2,loop of 9
sub2 thread sequence of 0,loop of 9
sub2 thread sequence of 1,loop of 9
sub2 thread sequence of 2,loop of 9
sub3 thread sequence of 0,loop of 9
sub3 thread sequence of 1,loop of 9
sub3 thread sequence of 2,loop of 9
通过利用Condition条件,我们构建了三个条件,他们是指三个程序运行的条件,分别是c1,c2,c3,默认他们没有任何区别,无法区分属于哪个线程的条件,我们需要让他们配合一个变量flag使用,当flag=1的时候主线程main线程可以执行,当flag=2时子线程1可以执行,当flag=3的时候,子线程2可以执行,每个线程执行的时候,需要先获取锁,如果满足条件则执行,不满足条件则等待时机,运行完毕需要释放锁资源。
1270

被折叠的 条评论
为什么被折叠?



