java并发_线程通信

三.线程间通信

通信机制分为两种:共享内存机制和消息通信机制。volatile 和synchronized 是共享内存机制的实现方式,同时也要考虑通信的及时性和开销问题,等待/通知机制则保证了通信双方“高效沟通”的一种方式。管道输入/输出流则是消息通信机制的实现方式。线程间的执行顺序是通过Thread.join()来实现的。

1)volatile和synchronized关键字

概述:线程间通信在JAVA内存模型基础上的实现机制,是通过volatile,synchronized来体现的。

关键字volatile可以用来修饰字段(成员变量),就是告知程序任何对该变量的访问均需要
从共享内存中获取,而对它的改变必须同步刷新回共享内存,它能保证所有线程对变量访问
的可见性。

关键字synchronized可以修饰方法或者以同步块的形式来进行使用,它主要确保多个线程
在同一个时刻,只能有一个线程处于方法或者同步块中,它保证了线程对变量访问的可见性
和排他性。

volatile和synchronized的比较:

①volatile轻量级,只能修饰变量。synchronized重量级,还可修饰方法

②volatile只能保证数据的可见性,不能用来同步,因为多个线程并发访问volatile修饰的变量不会阻塞。

synchronized不仅保证可见性,而且还保证原子性,因为,只有获得了锁的线程才能进入临界区,从而保证临界区中的所有语句都全部执行。多个线程争抢synchronized锁对象时,会出现阻塞。

底层实现原理:对象的监视器

2)等待/通知机制

解决生产者,消费者消息通知及时性和难以降低开销的矛盾

等待/通知机制:是指一个线程A调用了对象O的wait()方法进入等待状态,而另一个线程B
调用了对象O的notify()或者notifyAll()方法,线程A收到通知后从对象O的wait()方法返回,进而
执行后续操作。上述两个线程通过对象O来完成交互,而对象上的wait()和notify/notifyAll()的
关系就如同开关信号一样,用来完成等待方和通知方之间的交互工作。

3) 等待/通知的经典范式

概述:

等待方:

  1. 获取对象的锁
  2. 如果条件不满足,那么调用对象的wait()方法,被通知后仍要检查条件
  3. 条件满足则执行对应的逻辑

通知方:

  1. 获得对象的锁
  2. 改变条件
  3. 通知所有等待在对象上的线程

用于线程之间的数据传输,而传输的媒介为内存

4)管道输入\输出流
	/**
	 * 管道输入/输出流
	 * @author uns
	 *
	 */
	public class Piped {

	public static void main(String[] args) {
		PipedReader reader = new PipedReader();
		PipedWriter writer = new PipedWriter();
		try {
			writer.connect(reader);//输入流和输出流进行连接
			Thread thread = new Thread(new Print(reader),"PrintThread");
			thread.start();
			int received = 0;
			while ((received = System.in.read()) !=-1) {
				System.out.println((char)received);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	static class Print implements Runnable {
		private PipedReader  reader;
		
		public Print(PipedReader reader) {
			this.reader = reader;
		}
		public void run() {
			int received = 0;
			try {
				while ((received = reader.read()) !=-1) {
					System.out.println((char)received);
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

用来维护线程的执行先后关系

5)Thread.join()

含义:thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。

启动10个线程,把上一个线程加入的到当前线程,执行Thread.join()方法,上一个线程执行完,再执行当前线程。

	 /**
	 * Thread.join()方法
	 * 维护线程执行顺序
	 * @author LeeRujun
	 *
	 */
	public class Join {

	public static void main(String[] args) {
		Thread thread = Thread.currentThread();//上一个线程
		for (int i = 0; i < 10; i++) {
			Thread thread2 = new Thread(new Domain(thread),String.valueOf(i));
			thread2.start();
			thread  =thread2;
		}
		try {
			TimeUnit.SECONDS.sleep(5);
			System.out.println(Thread.currentThread().getName());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
		
	}

	
	static class Domain implements Runnable{
		private Thread thread;
        
		public Domain(Thread thread) {
			this.thread = thread;
		}
		public void run() {
			try {
				thread.join();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName());
		}
		
	}
	}

线程之间数据存储结构

6)ThreadLocal

ThreadLocal,即线程变量,是一个以ThreadLocal对象为键、任意对象为值的存储结构

posted @ 2017-11-08 10:20  Free丶Will  阅读(150)  评论(0)    收藏  举报