java 线程通信原理_多线程基础(5)-Java线程间的通信

合理的使用Java多线程可以更好地利用服务器资源。一般来讲,线程内部有自己私有的线程上下文,互不干扰。但是当我们需要多个线程之间相互协作的时候,就需要我们掌握Java线程的通信方式。本文将介绍Java线程之间的几种通信原理。

5.1 锁与同步

在Java中,锁的概念都是基于对象的,所以我们又经常称它为对象锁。线程和锁的关系,我们可以用婚姻关系来理解。一个锁同一时间只能被一个线程持有。也就是说,一个锁如果和一个线程“结婚”(持有),那其他线程如果需要得到这个锁,就得等这个线程和这个锁“离婚”(释放)。

在我们的线程之间,有一个同步的概念。什么是同步呢,假如我们现在有2位正在抄暑假作业答案的同学:线程A和线程B。当他们正在抄的时候,老师突然来修改了一些答案,可能A和B最后写出的暑假作业就不一样。我们为了A,B能写出2本相同的暑假作业,我们就需要让老师先修改答案,然后A,B同学再抄。或者A,B同学先抄完,老师再修改答案。这就是线程A,线程B的线程同步。

可以以解释为:线程同步是线程之间按照一定的顺序执行。为了达到线程同步,我们可以使用锁来实现它。

一个无锁的程序

public class Communication {

public static void main(String[] args){

ThreadA threadA = new ThreadA();

ThreadB threadB = new ThreadB();

threadA.start();

threadB.start();

}

public static class ThreadA extends Thread{

@Override

public void run() {

for(int i = 0; i < 10000; i++){

System.out.println("A");

}

}

}

public static class ThreadB extends Thread{

@Override

public void run() {

for(int i = 0; i < 10000; i++){

System.out.println("B");

}

}

}

}

输出:A、B为乱序的。

那我现在有一个需求,我想等A先执行完之后,再由B去执行,怎么办呢?最简单的方式就是使用一个“对象锁”:

public class Communication {

private static Object lock = new Object();

public static void main(String[] args){

new Thread(new ThreadA()).start();//谁先拿到锁,执行谁。

new Thread(new ThreadB()).start();

}

public static class ThreadA implements Runnable{

@Override

public void run() {

synchronized (lock){

for(int i = 0; i < 100000; i++){

System.out.println("A");

}

}

}

}

public static class ThreadB implements Runnable{

@Override

public void run() {

synchronized (lock){

for(int i = 0; i < 100000; i++){

System.out.println("B");

}

}

}

}

}

这里声明了一个名字为lock的对象锁。我们在ThreadA和ThreadB内需要同步的代码块里,都是用synchronized关键字加上了同一个对象锁lock。

上文我们说到了,根据线程和锁的关系,同一时间只有一个线程持有一个锁,那么线程就会等另一个线程执行完成后释放lock,才能获得锁lock。

5.2 等待/通知机制

上面一种基于“锁”的方式,线程需要不断地去尝试获得锁,如果失败了,再继续尝试。这可能会耗费服务器资源。

而等待/通知机制是另一种方式。

下面实现了交替执行,互相通知。

public class Communication {

private static Object lock = new Object();

public static void main(String[] args){

new Thread(new ThreadA()).start();//交替执行,互相通知

new Thread(new ThreadB()).start();

}

public static class ThreadA implements Runnable{

@Override

public void run() {

synchronized (lock){

for(int i = 0; i < 100000; i++){

System.out.println("A");

lock.notify();

try {

lock.wait();//

} catch (InterruptedException e) {

e.printStackTrace();

}

}

lock.notify();//通知wait

}

}

}

public static class ThreadB implements Runnable{

@Override

public void run() {

synchronized (lock){

for(int i = 0; i < 100000; i++){

System.out.println("B");

lock.notify();

try {

lock.wait();//

} catch (InterruptedException e) {

e.printStackTrace();

}

}

lock.notify();//通知wait

}

}

}

}

在这个Demo里,线程A和线程B首先打印出自己需要的东西,然后使用notify()方法叫醒另一个正在等待的线程,然后自己使用wait()方法陷入等待并释放lock锁。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值