黑马程序员_多线程通信

来源:互联网 发布:php 文章内链 编辑:程序博客网 时间:2024/05/22 10:47

android培训、java培训、期待与您交流!


 

线程间的通信:

实际上就是多个线程在操作同一个资源,只是操作的动作不同。

 

等待唤醒机制:

wait();notify();notifyAll();

都要在同步中使用,因为要对持有监视器的线程操作。

所以要用在同步中,因为只有同步才具有监视器。

 

为什么这些操作线程的方法要定义在Object类中呢?

 

因为这些方法在操作同步中线程时,都必须要标识他们所操作线程的锁。

只有同一个锁上的wait等待线程,可以被同一个锁上notify唤醒

不可以对不同锁中的线程进行唤醒操作。

即等待和唤醒操作必须针对同一个监视器(锁)。

而监视器可以是任意对象,所以可以被任意对象调用的方法就定义在Object类中。

package com.itheima.test9;

 

class Res

{

      private  Stringname;

      private  Stringsex;

      private  boolean flag=false;

    

    public  synchronized void setRes(Stringname,String sex ) {

       if(flag)

           try{this.wait();}catch(Exception e){}

       this.name = name;

       this.sex=sex;

        flag = true;

         this.notify();

    }

    public synchronized  void out(){

    if(!flag)

        try{ this.wait();}catch(Exception e){}

    System.out.println(name+"------"+sex);

    flag=false;

    this.notify();

    }

}

 

class Input implements Runnable

{

       private Resr;

       Input(Res r){

              this.r = r;

       }

       public void run(){

              int x = 0;

              while (true)

              {                  

                if (x == 0){   

                        r.setRes("mike","man");

                }else{

                   r.setRes("丽丽","女女女女女女");                                    }   

                

                            x = (x+1)%2;

                     }   

                }               

              }

      

 

class Output implements  Runnable

{

       private Resr;

       Output(Res r){

              this.r = r;

       }

 

       public void run(){

              while (true)

              {

                  r.out();

       }

       }

       }

class InputOutputDemo

{

       public static void main(String[] args)

       {

              Res r = new Res();

 

 

             new Thread(new Input(r)).start();

             new Thread(new Output(r)).start();

 

       }

}

--------------------------------------------------------------------------------------------------

生产者消费者问题(Producer-Customer)

 

为什么要使用while和notifyAll?

1.当被唤醒的线程回复执行资格,需要再次判断,所以使用while循环。

2.因为需要唤醒对方线程,只用notify,容易出现只唤醒本方线程的情况某导致程序中所有线程等待。

 

JDK1.5以后版本中提供了多线程升级解决方案:

将同步synchronized替换成现实lock操作。

将Object类中的wait,notify,notifyAll替换成了Condition对象。该对象可以通过Lock锁进行获取。

 

以下示例实现了本方只唤醒对方线程的操作的优化(原操作为唤醒全部线程)

package com.itheima.test9;

 

class Resourse

{

       private Stringname;

       private int count = 1;

       private boolean flag = false;

      

       //使用synchronized同步

       public synchronized void set(String name){

             while(flag)//如果用if,唤醒阻塞线程的话,不会判断flag,会出现存一次取多次或者存多次取一次的情况。

                     try{this.wait();}catch (Exception e){}

              this.name = name+"--"+count++;

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

              flag = true;

              this.notifyAll();//如果只是notify(),存在全部线程阻塞情况。

       }

 

       public synchronized void get(){

              while(!flag)//如果用if,唤醒阻塞线程的话,不会判断flag,会出现存一次取多次或者存多次取一次的情况。

                     try{this.wait();}catch (Exception e){}

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

              flag = false;

              this.notifyAll();//如果只是notify(),存在全部线程阻塞情况。

       }

     

}

 

class Producerimplements Runnable

{

       Resourse r = new Resourse();

       Producer(Resourse r){

              this.r = r;

       }

       public void run(){

              while(true){

                     r.set("商品");

              }

       }

 

}

class Consumerimplements Runnable

{

       Resourse r = new Resourse();

       Consumer(Resourse r){

              this.r = r;

       }

 

       public void run(){

              while(true){

                     r.get();

              }

       }   

}

 

class ProducerConsumerDemo

{

       public static void main(String[] args)throws Exception{

              Resourse r = new Resourse();

              Producer pro = new Producer(r);

              Consumer con = new Consumer(r);

 

              Thread t1 = new Thread(pro);

              Thread t2 = new Thread(pro);

              Thread t3 = new Thread(pro);

              Thread t4 = new Thread(con);

              Thread t5 = new Thread(con);

              Thread t6 = new Thread(con);

              t1.start();

              t2.start();

              t3.start();

              t4.start();//t4.join();主线程放弃执行权,等到t4结束才被重新恢复。t1234交替进行。

              t5.start();

              t6.start();

       }

}

       //使用lock进行互斥

   package com.itheima.test6;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

 

class Resourse

{

       private Stringname;

       private int count = 1;

       private boolean flag = false;

       Lock lock=new ReentrantLock();

  Condition condition_pro=lock.newCondition();

  Condition condition_con=lock.newCondition();

 

  public  void set(String name) throwsInterruptedException{

       lock.lock();

       try {

             while(flag)

                  condition_pro.await();

               this.name = name+"--"+count++;

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

              flag = true;

              condition_con.signal();

      

       }finally{

              lock.unlock();

              }

           }

       public synchronized void get() throwsInterruptedException{

        lock.lock();  

       try

       while(!flag)

                condition_con.await();

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

              flag = false;

              condition_pro.signal();

       }finally{

              lock.unlock();

       }

     

}

}  

 

class Producerimplements Runnable

{

       Resourse r = new Resourse();

       Producer(Resourse r){

              this.r = r;

       }

       public void run(){

              while(true){

                   try {r.set("商品");}catch(Exception e){}

              }

       }

 

}

class Consumerimplements Runnable

{

       Resourse r = new Resourse();

       Consumer(Resourse r){

              this.r = r;

       }

 

       public void run(){

              while(true){

                try {r.get();}catch(Exception e){}

              }

       }   

}

 

class ProducerConsumerDemo2

{

       public static void main(String[] args)throws Exception{

              Resourse r = newResourse();

              Producer pro = new Producer(r);

              Consumer con = new Consumer(r);

 

              Thread t1 = new Thread(pro);

              Thread t2 = new Thread(pro);

              Thread t3 = new Thread(pro);

              Thread t4 = new Thread(con);

              Thread t5 = new Thread(con);

              Thread t6 = new Thread(con);

              t1.start();

              t2.start();

              t3.start();

              t4.start();

              t5.start();

              t6.start();

       }

}

 

--------------------------------------------------------------------------------------------------

扩展:

*************************************************

java.lang.Thread  setDaemon(boolean on)

将该线程标记为守护线程或用户线程(后台线程)。当正在运行的线程都是守护线程时,Java 虚拟机退出。

该方法必须在启动线程前调用。

参数:

on - 如果为 true,则将该线程标记为守护线程。

*************************************************

join();等待该线程终止。

public final void join()

                throwsInterruptedException

当A线程执行到了B线程的join方法时,A线程就会等待。等B线程执行完,A才会执行。

join可以用来临时加入线程执行。

当B线程阻塞时,清除A的Interrupted状态,可以恢复其执行状态。

*************************************************

toString();

public String toString()返回该线程的字符串表示形式,包括线程名称、优先级和线程组。

覆盖:类 Object 中的 toString

返回:该线程的字符串表示形式。

*************************************************

setPriority( int newPriority )

public final void setPriority(int newPriority)更改线程的优先级。

 

所有线程包括主线程的默认优先级是5,优先级范围为[1,10];

MAX_PRIORITY(10),MIN_PRIORITY(1),NORM_PRIORITY(5),是该Thread类里的常量。

*************************************************

yield()

public static void yield()

暂停当前正在执行的线程对象,并执行其他线程。

--------------------------------------------------------------------------------------------------

开发时线程的编写方法:

class ThreadTest{

     

       public static void  main(String[] args){

            

              new Thread()[

                     publicvoid run(){

                            //执行内容

                     }

              }.start();

 

              Runnable rbl =new Runnable(){

                     publicvoid run(){

                            //执行内容

                     }

              };

       }

}


0 0
原创粉丝点击