1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > java 山洞过火车 java_Java多线程之生产者消费者模型

java 山洞过火车 java_Java多线程之生产者消费者模型

时间:2020-09-20 06:12:27

相关推荐

java 山洞过火车 java_Java多线程之生产者消费者模型

线程间的通讯

wait()在对象上等待,等待通知(在等待过程中释放对象锁、等待必须在同步块内、这个对象就是同步锁)《让线程进入阻塞状态,将线程放入等待池中》

notify()通知在这个对象上等待的一个线程,唤醒它,让它不再等下去(必须在同步块内调用,同步锁必须是调用这个方法的对象)《》

notifyAll()和notify()差不多,区别在于是通知在这个对象上等待的所有线程

注意:线程间通讯的几个方法()

总结:wait、notify、notifyAll必须是同步代码块中被调用,

wait()在对象上等待,等待通知(在等待过程中释放对象锁、等待必须在同步块内、这个对象就是同步锁)

//要在这个线程中等待

public class Wifeextends Thread {

private Object message;//等待对象,同时也是同步锁

public Wife(Object message) {

this.message = message; //初始化,从外部传入

}

public void run(){

synchronized (message){//wait动作必须在一个同步块内部,而且对象锁必须是等待的对象

System.out.println("开始等待");

try {

message.wait();//在对象进行等待,等待过程中释放锁,另一线程的同步块得以执行

System.out.println("收到音讯,结束等待");

} catch(InterruptedException e) {

// TODOAuto-generated catch block

e.printStackTrace();

}

}

}

}

public class Husband{

public static void main(String[] args){

Object message = new Object(); //创建对象

Wife t = newWife(message); //新建线程,传入对象

t.start();//启动

System.out.println("上京赶考");

try {

Thread.sleep(5000);

} catch (InterruptedExceptione) {

// TODOAuto-generated catch block

e.printStackTrace();

}

System.out.println("考上状元");

System.out.println("飞鸽传书");

synchronized (message){//notify动作必须在同步块内,而且对象锁必须是调用通知的对象

message.notify();//通知在这个对象上等待的线程,当这个同步块结束,通知的那个线程的wait就返回并继续执行

}

}

}

notify()通知在这个对象上等待的一个线程,唤醒它,让它不再等下去(必须在同步块内调用,同步锁必须是调用这个方法的对象)

notifyAll()和notify()差不多,区别在于是通知在这个对象上等待的所有线程

public class CowManextends Thread {

private Object message;

public CowMan(Object message) {

this.message = message;

}

public void run(){

synchronized (message) {

System.out.println("牛郎等待");

try {

message.wait();

} catch(InterruptedException e) {

// TODOAuto-generated catch block

e.printStackTrace();

}

System.out.println("牛郎去鹊桥");

}

}

}

public class Fairyextends Thread {

private Object message;

public Fairy(Object message) {

this.message = message;

}

public void run(){

synchronized (message) {

System.out.println("织女等待");

try {

message.wait();

} catch(InterruptedException e) {

// TODOAuto-generated catch block

e.printStackTrace();

}

System.out.println("兴冲冲跑去鹊桥相会");

}

}

}

public static voidmain(String[] args) throws Exception {

Object message = newObject();//创建共同使用的信息对象

CowMan cowMan = newCowMan(message);//牛郎和织女都等待同一个信息,七月初七到来的信息

Fairy fairy = newFairy(message);

cowMan.start();

fairy.start();

for(int i=1;i<=7;i++){

System.out.println("七月初"+i);

Thread.sleep(1000);

}

synchronized (message) {

message.notifyAll();//通知在这个对象上等待着的所有线程,牛郎和织女

}

}

public class Demo {

publicstatic void main(String[] args) {

Resouser = new Resouse("苹果");

newProduce("生产者", r).start();

newConsumer("消费者", r).start();

}

}

/**

* 消费者类

*

*/

class Consumer extends Thread {

Resouser;

publicConsumer(String name, Resouse r) {

super(name);

this.r= r;

}

@Override

publicvoid run() {

//不停拿资源

while(true) {

r.get();

}

}

}

class Produce extends Thread {

Resouser;

publicProduce(String name, Resouse r) {

super(name);

this.r= r;

}

@Override

publicvoid run() {

//不停生产

while(true) {

r.put();

}

}

}

class Resouse {

Stringname;

intid;

booleanflag; // 记录有没有资源

publicResouse(String name) {

this.name= name;

}

/**

* 放资源

*/

publicsynchronized void put() {

try{

if(flag) {

wait();//让线程进入等待状态(阻塞状态的一种),直到被notify()方法唤醒

}

//生产资源

id++;

System.out.println(Thread.currentThread().getName()+ "...生产了....."

+name + id);

flag= true;

//通知消费者

notify();

Thread.sleep(500);

}catch (InterruptedException e) {

//TODO Auto-generated catch block

e.printStackTrace();

}

}

//【同步方法的实质是同步代码块,同一个类中的不同行为的同步,是可行的。同步锁是当前对象,

//即在多线程中同一时间片段中,对象只会调用类中同步的其中一个同步方法】

/**

* 取资源

*/

public/*synchronized */void get() {

synchronized(this) {//同步锁就是对象监视器,他只会监控同步锁对应的代码块中的代码

try{

if(!flag) { // 没有资源就等待生产

wait();

}

System.out.println(Thread.currentThread().getName()

+"...消费了...." + name + id);

flag= false; // 消费完得告诉生产者没有资源了

//通知生产者

notify();

Thread.sleep(500);

}catch (InterruptedException e) {

//TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

publicclass Demo {

public static void main(String[] args){

Resouse r = newResouse("苹果");

new Produce("生产者1号",r).start();

new Consumer("消费者1号",r).start();

new Produce("生产者2号", r).start();

new Consumer("消费者2号",r).start();

new Produce("生产者3号",r).start();

}

}

/**

* 消费者类

*

*/

classConsumer extends Thread {

Resouse r;

public Consumer(String name, Resouse r){

super(name);

this.r = r;

}

@Override

public void run() {

// 不停拿资源

while (true) {

r.get();

}

}

}

classProduce extends Thread {

Resouse r;

public Produce(String name, Resouse r){

super(name);

this.r = r;

}

@Override

public void run() {

// 不停生产

while (true) {

r.put();

}

}

}

classResouse {

String name;

int id;

boolean flag; // 记录有没有资源

public Resouse(String name) {

this.name = name;

}

/**

* 放资源

*/

public synchronized void put() {

try {

while (flag) {

wait();// 让线程进入等待状态(阻塞状态的一种),直到被notify()方法唤醒

}

// 生产资源

id++;

System.out.println(Thread.currentThread().getName()+ "...生产了....."

+name + id);

flag = true;

// 通知消费者

notifyAll();

Thread.sleep(500);

} catch (InterruptedExceptione) {

// TODOAuto-generated catch block

e.printStackTrace();

}

}

// 【同步方法的实质是同步代码块,同一个类中的不同行为的同步,是可行的。同步锁是当前对象,

// 即在多线程中同一时间片段中,对象只会调用类中同步的其中一个同步方法】

/**

* 取资源

*/

public/* synchronized */void get() {

synchronized (this) {//同步锁就是对象监视器,他只会监控同步锁对应的代码块中的代码

try {

while(!flag) { // 没有资源就等待生产

wait();

}

System.out.println(Thread.currentThread().getName()

+"...消费了...."+ name + id);

flag =false; // 消费完得告诉生产者没有资源了

// 通知生产者

notifyAll();

Thread.sleep(500);

} catch(InterruptedException e) {

// TODOAuto-generated catch block

e.printStackTrace();

}

}

}

}

多生产者多消费者的问题

1、 if语句换成while语句

可以保证在生产或消费之前都先判断一次资源的情况

2、 notity方法换成notifyAll方法

可以保证每次都能唤醒对方的线程

在JDK1.5之后,可以使用Lock接口和Condition接口来解决以上问题

通过Lock接口也可以实现线程的同步处理,并且可以让同步处理变得更加灵活(需要手动实现获取锁和释放锁的操作)

//示例代码

//创建Lock对象(可以将Lock对象理解为原来的锁对象)

try{

//被同步的代码

}finally {

}

Condition对象将原先在Object类中的监视器方法(wait、notify、notifyAll)抽取出来进行封装,每一个Condition对象都是一个等待池,一个Lock对象可以绑定多个Condition对象,这样一来可以让线程间的通讯操作变得更加灵活。

//创建Condition对象,并和指定的Lock对象绑定

Lock lock = ...;

Condition condition = lock.newCondition();

线程间通讯的三个方法

1)await():替代wait方法

2)signal():替代notify方法

3)signalAll():替代notifyAll方法

/*

* 有5辆火车要过山洞,但确保山洞同时只能有一辆火车通过(过山洞需要1秒),打印输出火车通过的顺序。

* (过山洞的顺序是不可控的,只要保证同一时间只有一辆火车能通过山洞即可)

* 提示:使用线程同步,一辆火车就是一个线程

*/

publicclass LockDemo {

public static void main(String[] args){

// TODO Auto-generated methodstub

newTrain("火车1").start();

new Train("火车2").start();

new Train("火车3").start();

new Train("火车4").start();

new Train("火车5").start();

}

}

classTrain extends Thread{

//创建Lock对象

static Lock lock = new ReentrantLock();

public Train(String name){

super(name);

}

@Override

public void run() {

//获取锁

lock.lock();

try {

System.out.println(getName()+"过山洞.....");

Thread.sleep(1000);

} catch (InterruptedExceptione) {

// TODOAuto-generated catch block

e.printStackTrace();

}finally{

//释放锁

lock.unlock();

}

}

}

publicclass Demo {

public static void main(String[] args){

// TODO Auto-generated methodstub

Resource r = newResource("苹果");

new Producer("生产者1号",r).start();

new Producer("生产者2号",r).start();

new Consumer("消费者1号",r).start();

new Consumer("消费者2号",r).start();

new Consumer("消费者三号", r).start();

}

}

/*

* 消费者类

*/

classConsumer extends Thread {

Resource r;

public Consumer(String name, Resourcer) {

super(name);

this.r = r;

}

@Override

public void run() {

while (true) {

r.get();

}

}

}

/*

* 生产者类

*/

classProducer extends Thread {

Resource r;

public Producer(String name, Resourcer) {

super(name);

this.r = r;

}

@Override

public void run() {

while (true) {

r.put();

}

}

}

/*

* 资源类

*/

classResource {

String name;

int id;

boolean flag; // 记录有没有资源

// Lock对象,用于替代同步代码块

Lock lock = new ReentrantLock();

// 创建两个等待池

// 生产者线程用的等待池

Condition producerCon =lock.newCondition();

// 消费者线程用的等待池

Condition consumCon =lock.newCondition();

public Resource(String name) {

this.name = name;

}

// 放资源

public void put() {

lock.lock();

try {

while (flag) {

// 将当前线程(生产者线程放入等待池)

producerCon.await();// 替代了wait方法

}

// 生产资源

id++;

System.out.println(Thread.currentThread().getName()+ "...生产了...."

+name + id);

flag = true;

// 通知消费者消费

// 唤醒消费者等待池中的线程

consumCon.signal();

Thread.sleep(500);

} catch (InterruptedExceptione) {

// TODO Auto-generatedcatch block

e.printStackTrace();

} finally {

lock.unlock();

}

}

public void get() {

lock.lock();

try {

while (!flag) {

consumCon.await();

}

// 消费资源

System.out.println(Thread.currentThread().getName()+ "....消费了...."

+name + id);

flag = false;

//通知生产者生产

producerCon.signal();

Thread.sleep(500);

} catch (InterruptedExceptione) {

// TODOAuto-generated catch block

e.printStackTrace();

}finally{

lock.unlock();

}

}

}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。