Java并发编程基础---(2)线程通信机制

写在前面:

    线程之间如果一直处于独立运行,并不会为我们的项目带来多大的价值,如果线程之间一直保持通信,则会带来巨大的的价值,而这篇博客将总结 volatile 和 synchronized 这两个维护线程之间通信的关键字。

    volatile关键字

    volatile用于修饰字段(成员变量),volatile的使用就是告诉线程对变量的访问,必须从共享内存中获取,而不会利用缓存,而且对变量的改变,必须同步刷新回共享内存。

    synchronized关键字

    用于修饰方法或者以同步块的形式来使用。确保多个线程在同一时刻,只能有一个线程处于方法或者同步块中。保证了线程对变量访问的排他性。

等待/通知机制

    等待、通知的相关方法

    

方法名称描述
notify通知一个在对象上等待的线程,使其从wait方法中返回,前提是获取到了对象的锁

notifyAll

通知所有等待在该对象上的线程
wait

调用该方法的线程会进入WAITING状态,只有等待其他线程的通知或中断才会返回

注意:当调用了wait方法后,就会释放对象的锁

wait(long)超时等待一段时间,如果没有通知就超时返回
wait(long,int)对于超时等待更加细粒度的控制,到纳秒级别
实例代码:
package test6;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

public class Test4 {
	static Object lock = new Object();
	static boolean flag = true;

	public static void main(String[] args) throws Exception {
		Thread waitThread = new Thread(new Wait(), "waitThread");
		waitThread.start();
		TimeUnit.SECONDS.sleep(1); // TimeUnit是枚举类
		Thread notifyThread = new Thread(new Notify(), "notifyThread");
		notifyThread.start();
	}

	static class Wait implements Runnable {

		@Override
		public void run() {
			synchronized (lock) {
				while (flag) {
					try {
						System.out.println(Thread.currentThread()+"flag is true wait"
					+new SimpleDateFormat("HH:mm:ss").format(new Date()));
						lock.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				System.out.println(Thread.currentThread()+"flag is false running"
						+new SimpleDateFormat("HH:mm:ss").format(new Date()));
			}
			
		}

	}

	static class Notify implements Runnable {

		@Override
		public void run() {
			synchronized (lock) {
				System.out.println(Thread.currentThread()+"hold lock.notify"
						+new SimpleDateFormat("HH:mm:ss").format(new Date()));
				lock.notifyAll();
				flag = false;
				try {
					TimeUnit.SECONDS.sleep(5);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			synchronized (lock) {
				System.out.println(Thread.currentThread()+"hold lock again sleep"
						+new SimpleDateFormat("HH:mm:ss").format(new Date()));
				try {
					TimeUnit.SECONDS.sleep(5);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}

	}
}

程序执行流程

    (1)定义了两个线程,线程Wait先启动,打印,然后调用了lock的wait方法,释放锁

    (2)此时线程Wait睡眠1秒

    (3)线程Notify启动,获得锁,调用notifyAll方法,将所有等待的线程都移到同步队列,并将flag设置为flase。

    (4)Notify线程睡眠5秒

    (5)Notify线程再次获得锁,再睡眠5秒

    (6)线程Notify获得锁,因为flag=false,所以不执行while循环内的内容。

控制台输出信息如下:
Thread[waitThread,5,main]flag is true wait22:14:19
Thread[notifyThread,5,main]hold lock.notify22:14:20
Thread[notifyThread,5,main]hold lock again sleep22:14:25
Thread[waitThread,5,main]flag is false running22:14:30
总结:
    在调用wait方法后,线程状态会由RUNNING变成WAITING,并会将当前线程放置到对象的等待队列。
    在调用notify方法,线程会从等待队列移动到同步队列。线程状态会从WAITING变成BLOCKED状态。
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值