本人第一篇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();
}
}
好啦,废话不多说,能让你们有所收获就好。