zoukankan      html  css  js  c++  java
  • Java——线程间通信问题

    
    wait和sleep区别:
    1.wait可以指定时间可以不指定。
        sleep必须指定时间。
    2.在同步时,对cpu的执行权和锁的处理不同。
        wait:释放执行权,释放锁。
        sleep:释放执行权,不释放锁。

    /*

     * 等待/唤醒机制

     * 设计的方法:

     * 1.wait():让线程处于等待状态,被wait的线程会被存储到线程池中。

     * 2.notify():唤醒线程池中的一个线程(任意)

     * 3.notifyAll():唤醒线程池中的所有线程。

     * 这些方法都必须定义在同步中。

     * 因为这些方法是用于操作线程状态的方法。必须要明确到底操作的是哪个锁上的线程。********

     * 

     * 为什么操作线程的方法定义在Object中:   因为这些方法都是监视器的方法,监视器其实就是锁。

     * 锁可以是任意的对象,任意的对象调用的方式一定定义在Object类中。

     * 

     * 

     * 生产者和消费者:

     */

    class Resrouce

    {

    private String name;

    private int count = 1;

    private boolean flag = false;

    public synchronized void set(String name)

    {

    while(flag)

    {

    try

    {

    this.wait();//让该线程睡着(等待)

        }

    catch (InterruptedException e)

    {

    // TODO: handle exception

    }

    }

    this.name = name + count;

    count++;

    System.out.println(Thread.currentThread().getName()+"....生产者。。。。"+this.name);

    flag = true;

    /*

     * notify唤醒任意一个会出现死锁问题

     */

    //notify();//去唤醒一个(睡着的的线程)

    //所以唤醒全部

    notifyAll();

        }


    public synchronized void out()

    {

    while(!flag)

    {

    try

    {

    this.wait();//让该线程睡着 

    }

    catch (InterruptedException e)

    {

    // TODO: handle exception

    }

    }

        System.out.println(Thread.currentThread().getName()+"-----------------消费者-"this.name);

        flag = false;

    /*

     * notify唤醒任意一个会出现死锁问题

     */

    //notify();//去唤醒一个(睡着的的线程)

    //所以唤醒全部

    notifyAll();

    }

    }

    //生产者

    class Producer implements Runnable

    {

    private Resrouce r;

    Producer(Resrouce r)

    {

    this.r = r;

    }

    @Override

    public void run()

    {

    // TODO Auto-generated method stub

    while(true)

    r.set("馒头");

    }

    }

    //消费者

    class Consumer implements Runnable

    {

    private Resrouce r;

    Consumer(Resrouce r)

    {

    this.r = r;

    }

    @Override

    public void run()

    {

    // TODO Auto-generated method stub

    while(true)

    r.out();

    }

    }

    public class ResourceTest

    {

    /**

     * @param args

     */

    public static void main(String[] args)

    {

    // TODO Auto-generated method stub

    Resrouce r = new Resrouce();

    Consumer c1 = new Consumer(r);

    Consumer c2 = new Consumer(r);

    Producer p1 = new Producer(r);

    Producer p2 = new Producer(r);

    Thread t1 = new Thread(p1);

    t1.start();

    Thread t2 = new Thread(p2);

    t2.start();

    Thread t3 = new Thread(c1);

    t3.start();

    Thread t4 = new Thread(c2);

    t4.start();

    }

    }

    ======================================================================


    import java.util.concurrent.locks.Condition;

    import java.util.concurrent.locks.Lock;

    import java.util.concurrent.locks.ReentrantLock;

    /*

     * 生产者和消费者:

     * 

     * jdk1.5以后将同步和锁封装成了对象。并将操作锁的隐式方式定义到了该对象中。将隐式动作变成了显示动作。*******************

    Lock接口:出现替代了同步代码块或者同步函数,将同步的隐式锁操作变成现实锁操作

    lock():获取锁。  通常需要定义在finally代码中。

    Condition接口: 出现替代了Object中的wait   notify   notifyAll方法。

            将这些监视器方法单独进行封装,变成Condition监视器对象   可以任意进行组合。

    await();

    signal();

    signalAll();

     */

    class Resrouce

    {

    private String name;

    private int count = 1;

    private boolean flag = false;

    Lock lock = new ReentrantLock();//定义一把锁

    //通过已有的锁  获取该锁上的监视器对象。

    Condition con = lock.newCondition();

    Condition Producer_con = lock.newCondition();//生产者的监视器

    Condition Consumer_con = lock.newCondition();//消费者的监视器

    public void set(String name)

    {

        lock.lock();//获取一把锁

    try

    {

    while(flag)

    {

    try

    {

    //con.await();

    Producer_con.await();//生产者等待   去唤醒一个消费者

    }

    catch (InterruptedException e)

    {

        // TODO: handle exception

    }

    }

    this.name = name + count;

    count++;

    System.out.println(Thread.currentThread().getName()+"....生产者。。。。"+this.name);

    flag = true;

    //con.signalAll();

    Consumer_con.signal();//唤醒消费者

    }

    catch (Exception e)

    {

        // TODO: handle exception

    }

    finally

    {

        lock.unlock();

    }

    }

    public  void out()

    {

        lock.lock();//获取锁

    try

    {

    while(!flag)

    {

    try

    {

    //con.await();

    Consumer_con.await();//让消费者等待    然后去唤醒一个生产者。。

    }

    catch (InterruptedException e)

    {

    // TODO: handle exception

    }

    }

        System.out.println(Thread.currentThread().getName()+"-----------------消费者-"this.name);

        flag = false;

    //con.signalAll();

    Producer_con.signal();//唤醒生产者

    }

    catch (Exception e)

    {

        // TODO: handle exception

    }

    finally

    {

        lock.unlock();

    }

    }

    }

    //生产者

    class Producer implements Runnable

    {

    private Resrouce r;

    Producer(Resrouce r)

    {

        this.r = r;

    }

    @Override

    public void run()

    {

    // TODO Auto-generated method stub

    while(true)

    r.set("馒头");

    }

    }

    //消费者

    class Consumer implements Runnable

    {

        private Resrouce r;

    Consumer(Resrouce r)

    {

        this.r = r;

    }

    @Override

    public void run()

    {

    // TODO Auto-generated method stub

    while(true)

    r.out();

    }

    }

    public class ResourceTest

    {

    /**

     * @param args

     */

    public static void main(String[] args)

    {

    // TODO Auto-generated method stub

    Resrouce r = new Resrouce();

    Consumer c1 = new Consumer(r);

    Consumer c2 = new Consumer(r);

    Producer p1 = new Producer(r);

    Producer p2 = new Producer(r);

    Thread t1 = new Thread(p1);

    t1.start();

    Thread t2 = new Thread(p2);

    t2.start();

    Thread t3 = new Thread(c1);

    t3.start();

    Thread t4 = new Thread(c2);

    t4.start();

    }

    }


    停止线程的方法:





    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    Oracle 安装报错 [INS-06101] IP address of localhost could not be determined 解决方法输入日志标题
    Linux下安装oracle数据库提示DISPLAY not set. Please set the DISPLAY and try again。
    redhat 关机注销命令详解
    VirtualBox的四种网络连接方式
    修改RedHat的系统显示时间
    insufficient memory to configure kdump(没有足够的内存)解决方法(待验证、待解决)
    xen坑随笔 heartbeat dpkg垃圾数据库清除
    tomcat 监控脚本
    负载均衡随笔
    GIT命令介绍
  • 原文地址:https://www.cnblogs.com/blogs-chao/p/4764926.html
Copyright © 2011-2022 走看看