java学习第十三天多线程的死锁和并发

package MoreThreadLearn;

import java.util.Set;

/*
多线程间的通信,多个线程都在处理同一个资源,但是处理的任务却不一样
生产者,消费者
通过同步,解决了没生产就消费的问题
但是出现了连续的生产没有消费的情况,和需求生产一个,消费一个的情况不符
使用了等待唤醒机制

wait();//该方法可以让线程处于冻结状态,并将线程临时存储到线程池中国
notify();//唤醒指定线程池中的任意一个线程
notifyAll();//唤醒指定线程池中的所有线程

这些方法必须使用在同步中,因为它们又来操作同步锁上的现成的状态的
在使用这些方法时,必须标识它们所属于的锁,标识方式就是  锁对象.wait();   锁对象.notify();    锁对象.notifyAll();
相同锁的notify(),可以获取相同锁的wait();
*/
/*
多生产多消费
问题1:
    重复生产,重复消费
    原因:经过复杂的(等、资格)分析,发现被唤醒的线程没有判断标记就开始工作了(生成或消费)
    导致了重复的生成和消费的发生
    解决:
    那就是被唤醒的线程必须判断标记
    使用while循环搞定

问题2:
    死锁了 。所有的线程都处于冻结状态
    原因:本方线程在唤醒时,又一次唤醒了本方线程。而本方线程循环判断标记,又继续等待
    而导致所有的线程都等待了

    解决:
    希望本方如果唤醒了对方线程,就可以解决
    可以使用notifyAll()方法
    那不是全唤醒了吗?是的,既有本方又有对方。但是本方醒后,会判断标记继续等待
    这样对方就有线程可以执行了
*/

public class ProduceConsumerDemo {
    public static void main(String[] args) {
//      创建资源
        Res res=new Res();
//      创建两个任务
        Producer producer=new Producer(res);
        Customers customers=new Customers(res);
        Thread t1=new Thread(producer);
        Thread t2=new Thread(customers);
        t1.start();
        t2.start();
    }
}
//描述资源
class Res{
    private String name;
    private int count=1;
    //定义标记
    private boolean flag;
    //提供给商品赋值的方法
    public synchronized void set(String name){      
        if(flag)//判断标记为true,执行wait,为false,就生产
            try {
            wait();     
            } catch (InterruptedException e) {}             
        this.name = name +"--"+count;
        count++;
        System.out.println(Thread.currentThread().getName()+"...生产者....."+this.name);
        //生产完毕,将标记改为notify()
        flag=true;
        //唤醒消费者
        notify();
    }
//  提供一个获取商品的方法
    public synchronized void get() {        
        if(!flag)
            try {
                wait();     
                } catch (InterruptedException e) {} 
        System.out.println(Thread.currentThread().getName()+"...消费者..."+this.name);
        //将标记改为false
        flag=false;
        //唤醒消费者
        notify();
    }
}
//生产者
class Producer implements Runnable{
    private Res res;
    public Producer(Res res) {
        this.res=res;
    }
    public void run(){
        while(true){
            res.set("面包");          
        }       
    }
}

//消费者
class Customers implements Runnable{
    private Res res;
    public Customers(Res res) {
    this.res=res;
    }
    public void run(){
        while(true){
            res.get();
        }       
    }
}

package MoreThreadLearn;
import java.util.concurrent.locks.*;
/*
解决了多生产多消费的效率问题
使用了JDK1.5 java.util.concurrent.locks包中的对象
lock接口:它的出现比synchronized有更多的操作
    lock():获取锁
    unlock():释放锁
同步代码块或者同步函数的锁的操作是隐式 的
JDK1.5  Lock接口,按照面向对象的思想,将锁单独封装成一个对象,并提供了对锁的显示操作

Lock接口就是同步的替代
1、将线程中的同步更换为Lock接口的形式

替换完运行失败了,因为wait没有同步区域,没有了所属的同步锁
同步升级了。其中锁已经不再是任意对象,而是Lock类型的对象
那么和任意对象绑定的监视方法,是不是也升级了,有了专门的和Lock类型锁的绑定的监视机器方法呢?
查阅api。Condition接口替代啦Object中的监视器方法

以前监视器方法封装到每一个对象当中
现在将监视器方法封装到Condition对象中
方法名为:await signal signalAll
obj作为锁,本身就是监视器方法
监视器对象Condition如何和
*/

/*
wait()和 sleep()的区别?
相同:可以让线程处于冻结状态
不同点:
    1、wait()可以指定时间。也可以不指定
    sleep()必须指定时间
    2、wait():释放资源,释放锁
    sleep():释放cpu资源,不释放锁
*/


/*
synchronized(obj){
    obj.wait();
    code ....
}
Synchronized(obj){
    obj.notifyAll();
}*/


public class ProducerCustomerThread {
    public static void main(String[] args) {
        Res res=new Res();
        Producer producer=new Producer(res);
        Consumer consumer=new Consumer(res);
//      创建线程
         Thread t1= new Thread(producer); 
         Thread t2 =new Thread(consumer);
         t1.start();
         t2.start();
    }
}

class Res2{
    private String name;
    private int count=1;
    private boolean flag;
    private Lock lock=new ReentrantLock();
    private Condition condition=lock.newCondition();
    public void set(String name){
        //获取锁
        lock.lock();
        try {
            while (flag)
                try {
                    condition.await();
                } catch (Exception e) {}
            this.name=name+"--"+count;
            count++;
            System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);

            flag=true;
            condition.signalAll();
        } finally {
            //释放锁
            lock.unlock();
        }
    }

    public void get(){
        lock.lock();
        try {
            while (!flag)//一定要记得用while判断
                try {
                    condition.await();
                } catch (Exception e) {}
            this.name=name+"--"+count;
            count++;
            System.out.println(Thread.currentThread().getName()+"...消费者..."+this.name);

            flag=false;
            condition.signalAll();//和while相对应的signalAll();   
        } finally {
            //释放锁
            lock.unlock();
        }
    }
}

class Consumer implements Runnable{
    private Res res;
    public Consumer(Res res) {
        this.res=res;
    }
    public void run(){
        while(true){
            res.get();      
        }       
    }
}

class Producers implements Runnable{
    private Res res;
    public Producers(Res res) {
    this.res=res;
    }
    public void run(){
        while(true){
            res.set("面包");  
        }       
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值