线程通讯需要到的重要方法:
wait():令当前线程挂起并放弃CPU、同步资源,使别的线程可访问并修改共享资源,而当前线程排队等候再次对资源的访问
notify():唤醒正在排队等待同步资源的线程中优先级最高者结束等待
notifyAll ():唤醒正在排队等待资源的所有线程结束等待.
/*
* 生产者(Productor)将产品交给店员(Clerk),而消费者(Customer)从店员处取走产品,
* 店员一次只能持有固定数量的产品(比如:20),如果生产者试图生产更多的产品,店员会叫生产者停一下,
* 如果店中有空位放产品了再通知生产者继续生产;如果店中没有产品了,店员会告诉消费者等一下,
* 如果店中有产品了再通知消费者来取走产品。
* 生产者和消费者线程,如果都各有一个,那么唤醒的时候可以使用notify()唤醒,因为只有一个线程等待唤醒。
* 但是如果生产者和消费者线程是多个,那么使用notify()唤醒就会随机唤醒,就有肯能造成错误,这个时候需要使用notifyAll()。
* 需要将原来使用if判断的wait判断块改成使用while判断。
*/
public class TestClerk {
public static void main(String[] args) {
// TODO Auto-generated method stub
Clerk clerk = new Clerk();
Productor p = new Productor(clerk);
Productor p1 = new Productor(clerk);
Productor p2 = new Productor(clerk);
p.start();
p1.start();
p2.start();
Customer c = new Customer(clerk);
Customer c1 = new Customer(clerk);
Customer c2 = new Customer(clerk);
c.start();
c1.start();
c2.start();
}
}
class Clerk {
private int product = 20;
public int getProduct() {
return product;
}
public void setProduct(int product) {
this.product = product;
}
// 保存一个商品
public synchronized void save() {
//if(product >= 20){//只有一个消费线程的时候可以使用if判断。
while(product >= 20){//有多个消费线程的时候需要使用while。
System.out.println("现在商品已经达到上限,先让消费线程消费一会儿吧~~~~~~~~~~~~~~~~");
try {
this.wait();//当前线程进入等待状态
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
product++;
System.out.println("生产线程生产了一个商品,此时商品数量是:" + getProduct());
//this.notify();//唤醒另外一个线程。
this.notifyAll();//唤醒所有线程。
}
// 消费一个商品
public synchronized void get() {
//if(product <= 0){//只有一个生产线程的时候可以使用if
while(product <= 0){//有多个生产线程的时候需要是while
System.out.println("当前已经没有任何商品了,让生产线程生产一会儿吧======================");
try {
this.wait();//当前线程进入等待状态
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
product--;
System.out.println("消费线程消费了一个商品,此时商品数量是:" +getProduct());
//this.notify();//唤醒另外一个线程。
this.notifyAll();//唤醒所有线程
}
}
class Productor extends Thread {
private Clerk clerk;
public Productor(Clerk clerk) {
super();
this.clerk = clerk;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
clerk.save();
}
}
}
class Customer extends Thread {
private Clerk clerk;
public Customer(Clerk clerk) {
super();
this.clerk = clerk;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
clerk.get();
}
}
}
使用两个线程打印 1-100. 线程1, 线程2 交替打印
public class TestShowOneTwo {
public static void main(String[] args) {
// TODO Auto-generated method stub
ShowNumberTwo st = new ShowNumberTwo();
Thread one = new Thread(st);
one.setName("肯德基线程");
one.start();
Thread two = new Thread(st);
two.setName("麦当劳线程");
two.start();
}
}
class ShowNumberTwo implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
synchronized (this) {
this.notify();
System.out.println(Thread.currentThread().getName() + "线程正在打印===================="+i);
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}