线程通信
概述
1、线程通讯指的是多个线程通过消息传递实现相互牵制,相互调度,即线程间的相互作用。
2、线程通信中涉及的三个方法:
(1)wait():此方法一旦执行,当前线程就进入阻塞状态,并释放同步监视器(锁资源)。
(2)notify():此方法一旦执行,就会唤醒被 wait 的一个线程。如果有多个线程被 wait,就唤醒优先级最高的那个。
(3)notifyAll():此方法一旦执行,就会唤醒所有被 wait 的线程。
3、wait()、notify()、notifyAll()三个方法必须使用在同步代码块或者同步方法中。
4、wait()、notify()、notifyAll()三个方法是定义在java.lang.Object类中。
线程通信的经典案例
两个线程交替打印1-100的数字
public class ThreadComunicationDemo {
/*这是一个程序入口*/
public static void main(String[] args) {
Comunication c = new Comunication();
Thread t1 = new Thread(c,"线程1");
Thread t2 = new Thread(c,"线程2");
t1.start();
t2.start();
}
}
class Comunication implements Runnable{
/*共享资源*/
int num = 1;
@Override
public void run() {
while(true){
synchronized (this) {
/*当以个进入wait后就释放了锁,此时第二个线程拿到锁后并释放被wait的线程*/
this.notify();
if (num <= 100) {
System.out.println(Thread.currentThread().getName() + ":" + num);
num++;
} else {
break;
}
/*一个线程输出一个数字后就自行进入wait*/
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
生产者消费者问题
问题描述:
生产者(Productor)将产品放在柜台(Counter),而消费者(Customer)从柜台处取走产品,生产者一次只能生产固定数量的产品(比如:1), 这时柜台中不能再放产品,此时生产者应停止生产等待消费者拿走产品,此时生产者唤醒消费者来取走产品,消费者拿走产品后,唤醒生产者,消费者开始等待.
/**
* @function 生产者的线程
*/
public class Productor implements Runnable {
/*共享资源*/
private Counter counter;//不能直接对柜台进行实例化,因为消费者和生产者同时实例柜台,他们的商品库存就是分别为1,所以需要在main方法中实例化,然后传到两个线程
public Productor(Counter counter) {
this.counter = counter;
}
@Override
public void run() {
//生产者生产物品
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
counter.getNum();
}
}
}
/**
* @function 消费者线程
*/
public class Customer implements Runnable {
//共享资源
private Counter counter;
public Customer(Counter counter) {
this.counter = counter;
}
@Override
public void run() {
//消费者消费物品
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
counter.buyNum();
}
}
}
/**
* @function 柜台 两个线程的共享资源 库存永远保持1
*/
public class Counter {
private static int num = 1; //库存数量
/**
* 消费者买一个商品,库存-1
*/
public synchronized void buyNum(){
//库存为0时,让消费者等待
if (num==0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
//库存不为0时,此时从商品柜台买走一个物品,唤醒生产者的线程,生产者生产东西
System.out.println(Thread.currentThread().getName()+"买了1件物品");
num-=1;
notify();
}
}
/**
* 生产者生产一个商品,库存+1
*/
public synchronized void getNum(){
//库存为1时,让生产者等一等,不要生产东西
if (num==1){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
//库存不满时,生产者生产,同时唤醒消费者线程买东西
System.out.println(Thread.currentThread().getName()+"生产1件物品");
num+=1;
notify();
}
}
}
/**
* @function
*/
public class Test {
/*这是一个程序入口*/
public static void main(String[] args) {
/*共享资源*/
Counter counter = new Counter();
Productor productor = new Productor(counter);
Thread thread = new Thread(productor,"生产者线程");
thread.start();
Customer customer = new Customer(counter);
Thread thread1 = new Thread(customer,"消费者线程");
thread1.start();
}
}