Java线程通信

       当线程在系统内运行时,线程的调度具有一定的透明性,程序通常无法准确控制线程的轮换执行,但Java也提供了一些机制来保证线程协调运行。

      假设有两个线程,一个存款线程,一个取款线程——规定只有当存款者线程存入钱之后,取款线程才能进取款;同时只有当存款线程存入的钱被取款线程取走之后,存款线程才能继续存款。要实现这一需求,就可以借助java的线程通信机制。

       java总共设置了三种线程通信方式:传统的线程通信、使用Condition控制线程通信、使用阻塞队列控制线程通信。本文主要阐述自己对Java传统的线程通信方法的一些见解。

传统的线程通信

       为了实现上述存款、取款功能,可以借助Object类提供的wait()、notify()、notifyAll()三个方法,但是这三个方法必须由同步监视器对象来调用。这可以分为以下两种情况。

  • 对于使用synchronized修饰的同步方法,因为该类的默认实例(this)就是同步监视器,所以可以在同步方法中直接调用这三种方法。示例代码如下:
public synchronized void draw(double drawAmount)
	{
		try
		{
			//如果flag为假,表明账户中还没有人存钱进去,取钱方法阻塞
			if(!flag)
			{
				wait();
			}
			else
			{
				//执行取钱操作
				System.out.println(Thread.currentThread().getName()+"取 钱:"+drawAmount);
				balance-=drawAmount;
				System.out.println("账户余额为:"+balance);
				//将标识账户是否已有存款的旗标设为false
				flag=false;
				//唤醒其他线程
				notifyAll();
			}
		}
		catch (InterruptedException ex)
		{
			ex.printStackTrace();
		}
	}

上面代码展示的是取钱方法,因为账户类的存取款方法可能需要并发修改Account类的成员变量,所以这两个方法都使用synchronized修饰成同步方法,此处,只展示了取款方法draw() ,在draw我们用flag作为一个旗标来标识账户中是否已有存款,当发现账户中已有存款时,我们调用了wait()方法来阻塞取钱线程,此时,调用draw方法的实例对象充当同步监视器,也就是this充当同步监视器,此时this可以省略,所以我们看到代码中,直接调用wait()方法来阻塞取钱线程。同理,我们在代码中也可以看到,当取钱程序执行完取钱操作之后需要调用notifyAll()方法来唤醒在同一同步监视器上等待的所有线程。

通过使用synchronized把方法修饰成同步方法的方式来实现线程通信需要注意的几点:

(1)当某些方法中可能涉及到对同一成员变量的并发修改时,则需要通过借助synchronized修饰这些方法来使方法变成同步方法

(2)在同步方法中,通过调用wait()方法来实现线程阻塞,此时,同步监视器为调用该同步方法的实例,故可省略不写。

(3)在同步方法中,通过调用notifyAll()方法来唤醒在同一同步监视器上等待的所有线程。

 

  • 对于使用synchronized修饰的同步代码块,同步监视器是synchronized后括号里的对象,所以必须使用该对象调用这三种方法。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值