JAVA学习日记: 线程(7)

深渊向深渊呼唤

今天学习了的主要内容:

1.什么是产生者消费者模型
2.sleep()与wait()两个方法之间的差异

产生者消费者模型:

	两个共享固定大小的缓冲区的线程,一个是往里面生成数据的,
	一个是往里面释放使用数据的,
	那么前者就是生产者,后者就是消费者。
	  		
  	生产者主要就是生成一定数量的数据在缓冲区供消费者线程使用,
  	一但到某个临界值,生产者就不会继续生产数据。
  		
  	消费者就是消耗生产者产生的数据的线程,
  	一旦数据到某个临界值,就不再消耗。

  	我们关键就是要控制这两者的临界值!!
  
  	解决方法:
  		生产者解决方法:
  				让生产者在临界值休眠,然后等消费者从缓冲区消耗多个或者一个数据之后再唤醒。
 		消费者解决方法:
  				当缓冲区到那个临界值的时候,让消费者休眠,等生产者放入数据之后再唤醒。

sleep()与wait()两个方法之间的差异:

	wait()方法是Object类提供的,sleep()方法是Thread类提供的。
 	wait()方法会把锁给打开,但是sleep()方法不会。
  	wait()方法只能用在同步方法里,sleep()方法可以用在任意地点。

Resourcese类(提供取钱存钱方法):

package LessonForThread07;

public class Resourcese 
{
	private int money = 0;
	
	public int getMoney() 
	{
		return money;
	}

	public void setMoney(int money) 
	{
		this.money = money;
	}

	public synchronized void save()
	{
		//if (this.getMoney() != 0)
		while (this.getMoney() != 0)//为了防止多个线程无序唤醒,我们将if换成while这样每进来一个线程就可以判断是否要wait了。
		{
			try 
			{
				//wait()方法只能使用在同步方法中!!!synchronized修饰
				wait();//使当前线程随调用这个方法的那个线程,等待另一个线程调用notify()方法唤醒时才继,他不能保证只有一个线程进来,它不锁定值
			} catch (InterruptedException e)
				{
					e.printStackTrace();
				}
		}
		
		this.setMoney(this.getMoney()+10);
		notify();//唤醒的是对方的wait,让当前调用线程wait唤醒另一个调用的线程苏醒。
		System.out.println("余额:"+this.getMoney());
	}
	
	public synchronized void draw()
	{
//		if (this.getMoney() == 0)
		while (this.getMoney() == 0)
		{
			try 
			{
				wait();
			} catch (InterruptedException e) 
				{
					e.printStackTrace();
				}
		}
		
		this.setMoney(this.getMoney()-10);
		notify();
		System.out.println("被取钱之后还剩余:"+this.getMoney());
	}
}

Producer类(生产者):

package LessonForThread07;

public class Producer implements Runnable
{
	private Resourcese save_money;
	
	public Producer(Resourcese save_money)
	{
		this.save_money = save_money;
	}

	@Override
	public void run() 
	{
		for (int i=0; i<5; i++)
		{
			try 
			{
				Thread.sleep(500);//存钱循环一次让出500ms
			} catch (InterruptedException e) 
				{
					e.printStackTrace();
				}
			
			save_money.save();
		}
	}
}

Customer类(消费者):

package LessonForThread07;

public class Customer implements Runnable
{
	private Resourcese save_money;
	
	public Customer(Resourcese save_money)
	{
		this.save_money = save_money;
	}

	@Override
	public void run() 
	{
		for (int i=0; i<5; i++)
		{
			try 
			{
				Thread.sleep(500);//取钱循环一次让出500ms
			} catch (InterruptedException e) 
				{
					e.printStackTrace();
				}
			
			save_money.draw();
		}
	}
}

ThreadTest05类(测试notify和wait):

package LessonForThread07;

public class ThreadTest05
{	
	public static void main(String[] args)
	{
		Resourcese money = new Resourcese();
		
		Producer p1 = new Producer(money);
		new Thread(p1).start();
		Producer p2 = new Producer(money);
		new Thread(p2).start();
		Producer p3 = new Producer(money);
		new Thread(p3).start();
		
		Customer c1 = new Customer(money);
		new Thread(c1).start();
		Customer c2 = new Customer(money);
		new Thread(c2).start();
		Customer c3 = new Customer(money);
		new Thread(c3).start();

//		Thread t1 = new Thread(p1);
//		t1.start();
//		Thread t2 = new Thread(c1);
//		Thread t3 = new Thread(p1);
//		t3.start();
//		Thread t4 = new Thread(c1);
//		Thread t5 = new Thread(p1);
//		t5.start();
//		Thread t6 = new Thread(c1);
//		Thread t7 = new Thread(p1);
//		t7.start();
//		Thread t8 = new Thread(c1);
//		
//		t2.start();
//		t4.start();
//		t6.start();
//		t8.start();
		
		try 
		{
			Thread.sleep(10000);
		} catch (InterruptedException e) 
			{
				e.printStackTrace();
			}
		System.out.println("完毕");
	}
}

本篇部分文字来源于:
	咕嘟咖啡杨海滨老师 — 《java编程语言高级特性》
	在这里十分感谢老师能够给我带来学习的激情。

2020.10.25
可以转载我的学习日记但请注明出处,谢谢。
本文章是本人学习笔记,不进行任何商用!也请别拿去商用!只为记录本人学习历程。
毕	
栏目