Java笔记-多线程之线程通信

线程通信介绍

本总结我对于JAVA多线程中线程之间的通信方式的理解,主要以代码结合文字的方式来讨论线程间的通信


线程通信简单举例加实现


举例

例如:
生产线程和消费线程之间要进行沟通,不生产就不消费,生产一个,消费一个。


分析:
经过我们分析得知,生产和消费线程一直在互相抢占CPU执行权。

一会儿生产好几个,一会儿连续卖好几个。而且中间还会出现,吕布 女、貂蝉 男的错误情况。

这种情况是因为生产是两步骤,第一步name赋值,第二部 gender 赋值。但是在这两步赋值的过程中线程被抢走,则赋值一半。

就会出现名字和性别不符的情况。

所以:生产的时候就不要消费,消费的途中就不要生产,不能互相抢。

那么我们要做的就是把生产和消费的线程同步起来,并且用同一把锁,锁起来,锁对象用 per ,也就是要生产的物品,正合适。


实现代码

注:为了看起来清晰,实体类用 Person 当货品了。

1.Person.java:

public class Person {
	public String name;
	public String gender;
	//用于判断是否有人(物品)
	public boolean hasPerson = false;
}

2.ProductThread.java:

public class ProductThread extends Thread {
	Person per;
	int num = 0;

	public ProductThread(Person per) {
		this.per = per;
	}

	@Override
	public void run() {
		while (num < 100) {
			synchronized (per) {
				if (per.hasPerson) {
					// 如果有人,需要让当前线程等待,等待消费线程去消费
					// 消费完了通知我,我来生产
					try {
						// 等待
						per.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				try {
					sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				if (num % 2 == 0) {
					per.name = "吕布";
					per.gender = "男";
				} else {
					per.name = "貂蝉";
					per.gender = "女";
				}
				num++;
				// 随即唤醒用当前锁对象作为同步锁对象的其他线程中的一个
				per.notify();
				per.hasPerson = true;
			}
		}
	}
}

3.SellThread.java:

public class SellThread extends Thread {
	Person per;
	int num = 0;

	public SellThread(Person per) {
		this.per = per;
	}

	@Override
	public void run() {
		while (num < 100) {
			synchronized (per) {
				if (!per.hasPerson) {
					// 如果没有人,需要让当前线程等待,等待生产线程去生产
					// 生产完了通知我,我来消费
					try {
						per.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				try {
					sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(per.name + "  " + per.gender);
				num++;
				per.hasPerson = false;
				// 唤醒用当前锁对象作为同步锁对象的其他所有线程
				per.notifyAll();
			}
		}
	}
}

4.Test.java:

public class Test {
	public static void main(String[] args) {
		Person per = new Person();
		ProductThread pt = new ProductThread(per);
		SellThread st = new SellThread(per);
		pt.start();
		st.start();
	}
}

wait()和sleep()的比较

wait() 可以让当前线程处于阻塞状态。
sleep()也可以让当前线程处于阻塞状态。
而且,两个方法参数都可以传入毫秒值,都是指定阻塞时间。


那么区别在哪里?

sleep()不会自动释放锁。
wait()会自动释放锁。


tips:
两个不同的线程类,不同的线程代码,但是只要保证运行起来,用的同步锁是同一个锁对象,那么同样可以实现同步。

你可能感兴趣的:(JavaSE,JavaSE-多线程)