多线程的设计

线程直接的通信:通过管道流进行简单的交互
public class ThreadDemo6 {
	public static void main(String[] args) {
		PipedOutputStream pos=null;
		PipedInputStream pis=null;
		try {
			pos=new PipedOutputStream();
			pis=new PipedInputStream(pos);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		Sender sender=new Sender(pos);
		Thread t1=new Thread(sender);
		Receiver receiver=new Receiver(pis);
		Thread t2=new Thread(receiver);
		t1.start();
		t2.start();
		
	}
}

class Sender implements Runnable {
	private OutputStream out;

	public Sender(OutputStream out) {
		super();
		this.out = out;
	}

	@Override
	public void run() {
		for (int i = 1; i <= 5; i++) {
			byte value = (byte) (Math.random() * 100);
			System.out.println("send value is " + value);
			try {
				out.write(value);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

class Receiver implements Runnable {
	private InputStream in;

	public Receiver(InputStream in) {
		super();
		this.in = in;
	}

	@Override
	public void run() {
		for (int i = 1; i <= 5; i++) {
			try {
				byte value = (byte) in.read();
				System.out.println("receiver value is " + value);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

有一个弊端就是在所有的数据写完后才能去读取,这样在写的时候一直占用内存,我们希望每写一点就能拿一点。看下边的实现:

线程直接的通信:使用Thread.yield()模拟一个生产者和消费者的模型
* 效率还是比较差。yield方法是主动放弃了cpu,又去竞争。
public class ThreadDemo7 {
	public static void main(String[] args) {
		FlagSend flagSend = new FlagSend();
		FlagRec flagRec = new FlagRec(flagSend);
		Thread t1 = new Thread(flagSend);
		Thread t2 = new Thread(flagRec);
		t1.start();
		t2.start();

	}
}

class FlagSend implements Runnable {
	int theValue;
	boolean flag;//是否有食物:true有食物

	@Override
	public void run() {
		for (int i = 1; i <= 5; i++) {
			while (flag) {
				Thread.yield();
			}
			theValue = new Random().nextInt(1000);// 制造食物
			System.out.println("send value is " + theValue);
			flag = true;// 等待食客去吃
		}
	}
}

class FlagRec implements Runnable {

	public FlagRec(FlagSend flagSend) {
		super();
		this.flagSend = flagSend;
	}
	private FlagSend flagSend;

	@Override
	public void run() {
		for (int i = 1; i <= 5; i++) {
			while (!flagSend.flag) {
				Thread.yield();
			}
			System.out.println("receiver value is " + flagSend.theValue);
			flagSend.flag = false;
		}
	}

}

yield方法是主动放弃了cpu,又去竞争。效率比较差,接收的人不知道是否send已经Ok了。我们希望我们发送以后就去提醒接收者去拿不是一直去在放弃。

线程直接的通信:wait/notify 任何一个对象都拥有一个线程等待池
* 挂在同一个对象的线程等待池中的线程之间可以互相唤醒 wait/notify是属于Object类的
* wait方法必须放入synchronized同步块中

/**
 * @author Janle
 *
 */
public class ThreadDemo8 {
	public static void main(String[] args) {
		Cooker cooker=new Cooker();
		Diners diners=new Diners(cooker);
		Thread t1=new Thread(cooker);
		Thread t2=new Thread(diners);
		//当程序只有守护线程时候程序退出。
		t2.setDaemon(true);
		t1.start();
		t2.start();
		
	}
}

class Cooker implements Runnable {
	boolean hasFood;
	int value;

	@Override
	public void run() {
		for (int i = 1; i <= 5; i++) {
			// 将锁挂到同一个线程等待池中
			synchronized (this) {
				try {
					while (hasFood) {// 使用while是因为存在虚假唤醒,不能使用if
						/**
						 * 在没有被通知、中断或超时的情况下,线程还可以唤醒一个所谓的虚假唤醒 (spurious wakeup)。
						 * 虽然这种情况在实践中很少发生,但是应用程序必须通过以下方式防止其发生,
						 * 即对应该导致该线程被提醒的条件进行测试, 如果不满足该条件,则继续等待。换句话说,等待应总是发生在循环中
						 */
						this.wait();//wait方法会释放钥匙
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				value = new Random().nextInt(1000);
				System.out.println("Cooker 生产食物 " + value);
				hasFood=true;
				this.notify();
			}
		}
	}
}

class Diners implements Runnable {
	private Cooker cooker;

	public Diners(Cooker cooker) {
		super();
		this.cooker = cooker;
	}

	@Override
	public void run() {
		for (;;) {
			// 将锁挂到同一个线程等待池中
			synchronized (cooker) {
				try {
					while(!cooker.hasFood){
						cooker.wait();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				System.out.println("Diners 消费食物 " + cooker.value);
				cooker.hasFood=false;
				cooker.notify();
			}
			
		}
	}
}


线程中的通讯:在实际的业务中的使用
public class ThreadDemo9 {
	public static void main(String[] args) {
		final Bussiness bus=new Bussiness();
		Thread t1=new Thread(new Runnable() {
			@Override
			public void run() {
				bus.send();
			}
		});
		Thread t2=new Thread(new Runnable() {
			@Override
			public void run() {
				bus.recived();
			}
		});t2.setDaemon(true);
		t1.start();
		t2.start();
	}
}

class Bussiness {
	boolean flag;
	int value;

	public void send() {
		for (int i = 0; i < 5; i++) {
			synchronized (this) {
				try {
					while (flag) {
						this.wait();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				value = new Random().nextInt(1000);
				System.out.println("send value is " + value);
				flag = true;
				this.notify();
			}
		}
	}

	public void recived() {
		while (true) {
			synchronized (this) {
				try {
					while (!flag) {
						this.wait();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				System.out.println("receive value is " + value);
				flag = false;
				this.notify();
			}
		}
	}
}

你可能感兴趣的:(thread)