线程学习笔记(一)
问题描述:生产者负责做馒头,做好馒头后放进指定的篓子里面,消费者消费该篓子里面的馒头。篓子里只能装一定量的馒头,满了以后生产者必须进入等待状态,消费者吃完馒头后也必须进入等待状态。
package com.sync;
public class ProductAndConsumer {
public static void main(String[] args) {
Basket b = new Basket();
Product p = new Product(b);
Consumer c = new Consumer(b);
new Thread(p).start();
new Thread(c).start();
}
}
class ManTou{
int id;
public ManTou(int id) {
this.id = id;
}
@Override
public String toString() {
return "ManTou"+id;
}
}
//装馒头的篮子
class Basket{
int index = 0; //相当于栈顶指针
ManTou[] manTous = new ManTou[6];
//往篮子里面放馒头
public synchronized void push(ManTou m){
while(index == manTous.length){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
manTous[index] = m;
index++;
}
//往篮子里面取馒头
public synchronized ManTou pop(){
while(index == 0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
index--;
return manTous[index];
}
}
//生产者
class Product implements Runnable{
Basket basket;
public Product(Basket basket) {
this.basket = basket;
}
public void run() {
for (int i = 0; i < 20; i++) {
ManTou m = new ManTou(i);
basket.push(m);
System.out.println("生产了"+m);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//消费者
class Consumer implements Runnable{
Basket basket;
public Consumer(Basket basket) {
this.basket = basket;
}
public void run() {
for (int i = 0; i < 20; i++) {
ManTou m = basket.pop();
System.out.println("消费了"+m);
try {
Thread.sleep((int)(Math.random()*1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
wait()、notify()、notifyAll()方法的作用:wait():导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
notify():唤醒在此对象监视器上等待的单个线程。
notifyAll():唤醒在此对象监视器上等待的所有线程。
wait()与sleep()的区别:
两个方法的共同点就是让当前线程进入等待状态。
不同点:
wait()之后,锁就不归我所有了,必须等醒过来后才能拥有该锁,并且必须要有人唤醒它才会醒过来
sleep()不同,锁还是归我所有,一段时间后会自动醒过来