Java多线程06:线程通信
synchronized实现了同步,但不能实现不同线程之间的消息传递
线程通信的三种方法(只能在同步方法和同步块中使用,否则抛出异常):
wait()方法,表示线程一直等待,直到其他线程通知,与sleep()不同,wait()会释放锁
notify()方法,唤醒一个处于等待的线程
notifyAll()方法,唤醒同一个对象上所有调用wait()方法的线程,优先级高的线程优先调度
管程法
利用缓冲区
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList();
Consumer consumer = new Consumer(arrayList);
Producer producer = new Producer(arrayList);
/**
* 生产消费各十次(注意不能在run()方法里循环十次,不然会生产完所有苹果再消费)
*/
for (int i = 0; i < 10; i++) {
new Thread(consumer).start();
new Thread(producer).start();
}
}
}
/**
* 定义消费者类
*/
class Consumer implements Runnable {
ArrayList<Integer> arrayList;
public Consumer(ArrayList arrayList){
this.arrayList = arrayList;
}
@Override
public void run() {
synchronized (arrayList) {
if (arrayList.size() == 0) {
System.out.println("苹果没有了,需要生产");
try {
/**
* 没有苹果时消费者进入等待,收到唤醒后才会继续执行后续的代码
* wait()方法让线程进入等待,释放锁给生产线程
*/
arrayList.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 为了避免生产完立即被消费,设置一个延时
*/
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (arrayList.size() != 0){
arrayList.remove(0);
System.out.println("消费了一个苹果,还剩" + arrayList.size() + "个");
}
/**
* notify()方法唤醒生产线程
*/
arrayList.notify();
}
}
}
/**
* 定义生产者类
*/
class Producer implements Runnable{
ArrayList<Integer> arrayList;
/**
* 定义缓冲区的大小
* 生产者将产品放入缓冲区,消费者从缓冲区拿出产品
*/
int max = 10;
public Producer(ArrayList arrayList){
this.arrayList = arrayList;
}
@Override
public void run() {
synchronized (arrayList) {
if (arrayList.size() == max) {
System.out.println("盘子满了,需要消费");
try {
arrayList.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
arrayList.add(1);
System.out.println("生产了一个苹果,还剩" + arrayList.size() + "个");
arrayList.notify();
}
}
}
信号灯法
利用标志位
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
/**
* 不同类的对象需要操作同一个标志位
* 因此创建一个Goods类,在其中定义标志位,然后将生产和消费的方法放在该类中去执行
*/
ArrayList<Integer> arrayList = new ArrayList();
Goods goods = new Goods(arrayList);
Consumer consumer = new Consumer(goods);
Producer producer = new Producer(goods);
for (int i = 0; i < 10; i++) {
new Thread(consumer).start();
new Thread(producer).start();
}
}
}
class Consumer implements Runnable{
Goods goods;
public Consumer(Goods goods){
this.goods = goods;
}
@Override
public void run() {
goods.consume();
}
}
class Producer implements Runnable{
Goods goods;
public Producer(Goods goods){
this.goods = goods;
}
@Override
public void run() {
goods.produce();
}
}
class Goods {
ArrayList<Integer> arrayList;
boolean flag = true;
public Goods(ArrayList<Integer> arrayList){
this.arrayList = arrayList;
}
public void produce(){
synchronized (arrayList) {
if (!flag) {
try {
arrayList.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
arrayList.add(1);
System.out.println("生产了一个苹果,还剩" + arrayList.size() + "个");
/**
* 反转标志位,让消费者线程运行
*/
flag = !flag;
arrayList.notify();
}
}
public void consume(){
synchronized (arrayList) {
if (flag) {
System.out.println("苹果没有了,需要生产");
try {
arrayList.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (arrayList.size() != 0){
arrayList.remove(0);
System.out.println("消费了一个苹果,还剩" + arrayList.size() + "个");
}
/**
* 反转标志位,让生产者线程运行
*/
flag = !flag;
arrayList.notify();
}
}
}