线程间的通信

所谓线程间的通信,无非就是线程之间相互协作,互相影响,数据交互。

 

1、不使用wait和notify

两个线程在不使用wait 和 notify的前提下,也能通过sleep和while来实现相互影响。两个线程对同一个变量做操作,并循环监控这个变量。

 

 

2、wait()和notify()

Wait()

方法wait() 的作用是使当前执行代码的线程进程等待,wait()是Object类的方法,该方法用来将当前线程置入“预执行队列”,并在wait()所在的代码行处停止执行,知道接到通知或者被中断为止。

在调用前线程必须获得该对象的对象级的锁,即只能在同步方法或者同步块中调用wait()方法。

执行wait后,当前线程释放锁,在从wait返回前,该线程与其他线程竞争重新获得锁。如果调用wait时没有适当的锁,则抛出异常, 因此不需要用try-catch语句进行异常捕获。

 

notify()

该方法用来通知那些可能等待该对象的对象锁的其他线程,如果有多个线程等待,则由线程规划器随机挑选出其中一个呈wait状态的线程,对其发出通知notify,并使它等待获取该对象的对象锁。

在执行notify时,当前线程不会马上释放锁,wait的线程也不能马上得到锁,需要等notify的线程执行完,也就是退出synchronized代码块后,才会释放锁。

notify在调用前线程必须获得该对象的对象级的锁,即只能在同步方法或者同步块中调用。

wait使线程停止运行,notify使停止的线程继续运行。

示例代码:

public class MyThread1 extends Thread {
   private Object lock;

   public MyThread1(Object lock) {
      super();
      this.lock = lock;
   }

   @Override
   public void run() {
      try {
         synchronized (lock) {
            System.out.println("开始  wait time=" + System.currentTimeMillis());
            lock.wait();
            System.out.println("结束  wait time=" + System.currentTimeMillis());
         }
      } catch (InterruptedException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }
   }
}





public class MyThread2 extends Thread {

   private Object lock;



   public MyThread2(Object lock) {

      super();

      this.lock = lock;

   }



   @Override

   public void run() {

      synchronized (lock) {

         System.out.println("开始  notify time=" + System.currentTimeMillis());

         lock.notify();

         System.out.println("结束  notify time=" + System.currentTimeMillis());

      }

   }

}


import extthread.MyThread1;

import extthread.MyThread2;



public class Test {

   public static void main(String[] args) {

      try {

         Object lock = new Object();



         MyThread1 t1 = new MyThread1(lock);

         t1.start();



         Thread.sleep(3000);



         MyThread2 t2 = new MyThread2(lock);

         t2.start();



      } catch (InterruptedException e) {

         e.printStackTrace();

      }

   }

}
 

 

wait 方法可以使调用该方法的线程释放共享资源的锁,然后从运行状态退出,进入等待队列,直到被再次唤醒。

 

notify 方法可以随机唤醒等待队列中等待同一共享资源的一个线程,并使该线程退出等待推列,进入运行状态,也就是说notify只通知一个线程,而被通知的线程是随机的。

 

notifyAll()  可以使所有正在等待队列中等待同一共享资源的全部线程,从等待状态退出,进入运行状态。此时,优先级最高的那个线程最先执行,也可能是随即执行,这要取决于JVM虚拟机的实现。

 

 

锁释放的情况:1、执行完同步代码块和方法,就会释放对象锁。

                              2、 实行同步代码块的过程中,遇到异常导致线程终止,锁也会被释放。

3、在执行同步代码块中,执行了wait方法,就会释放锁,该线程也很贵进入线程等待池,等待被唤醒。

 

 

3、Wait(long)和通知过早

wait(long) 等待某一段时间是否有线程对锁进行唤醒,如果超过这个时间则自动唤醒。

 

通知过早:nodify在wait之前运行,wait永远不能被唤醒。

示例代码:

 

package test;



public class MyRun {



   private String lock = new String("");

   private boolean isFirstRunB = false;



   private Runnable runnableA = new Runnable() {

      @Override

      public void run() {

         try {

            synchronized (lock) {

               while (isFirstRunB == false) {

                  System.out.println("begin wait");

                  lock.wait();

                  System.out.println("end wait");

               }

            }

         } catch (InterruptedException e) {

            e.printStackTrace();

         }

      }

   };



   private Runnable runnableB = new Runnable() {

      @Override

      public void run() {

         synchronized (lock) {

            System.out.println("begin notify");

            lock.notify();

            System.out.println("end notify");

            isFirstRunB = true;



         }

      }

   };



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



      MyRun run = new MyRun();



      Thread a = new Thread(run.runnableA);

      a.start();



      Thread.sleep(100);



      Thread b = new Thread(run.runnableB);

      b.start();



   }



}

 

 

4、管道通信

管道流是一种特殊的流,用于在不同线程之间传送数据。一个线程发送数据到输出管道,另一个线程中管道中读取数据。通过管道,实现不同线程减的通信。

  1. PipedInputStream和PipedOutputStream   字节流
  2. PipedReader和PipedWriter              字符流

 

  1. 字节流示例代码:

 

import java.io.PipedInputStream;



import service.ReadData;



public class ThreadRead extends Thread {



   private ReadData read;

   private PipedInputStream input;



   public ThreadRead(ReadData read, PipedInputStream input) {

      super();

      this.read = read;

      this.input = input;

   }



   @Override

   public void run() {

      read.readMethod(input);

   }

}




import java.io.PipedOutputStream;



import service.WriteData;



public class ThreadWrite extends Thread {



   private WriteData write;

   private PipedOutputStream out;



   public ThreadWrite(WriteData write, PipedOutputStream out) {

      super();

      this.write = write;

      this.out = out;

   }



   @Override

   public void run() {

      write.writeMethod(out);

   }



}




import java.io.IOException;

import java.io.PipedInputStream;



public class ReadData {



   public void readMethod(PipedInputStream input) {

      try {

         System.out.println("read  :");

         byte[] byteArray = new byte[20];

         int readLength = input.read(byteArray);

         while (readLength != -1) {

            String newData = new String(byteArray, 0, readLength);

            System.out.print(newData);

            readLength = input.read(byteArray);

         }

         System.out.println();

         input.close();

      } catch (IOException e) {

         e.printStackTrace();

      }

   }

}




import java.io.IOException;

import java.io.PipedOutputStream;



public class WriteData {



   public void writeMethod(PipedOutputStream out) {

      try {

         System.out.println("write :");

         for (int i = 0; i < 300; i++) {

            String outData = "" + (i + 1);

            out.write(outData.getBytes());

            System.out.print(outData);

         }

         System.out.println();

         out.close();

      } catch (IOException e) {

         e.printStackTrace();

      }

   }

}




    public static void main(String[] args) {



      try {

         WriteData writeData = new WriteData();

         ReadData readData = new ReadData();



         PipedInputStream inputStream = new PipedInputStream();

         PipedOutputStream outputStream = new PipedOutputStream();



         // inputStream.connect(outputStream);

         outputStream.connect(inputStream);



         ThreadRead threadRead = new ThreadRead(readData, inputStream);

         threadRead.start();



         Thread.sleep(2000);



         ThreadWrite threadWrite = new ThreadWrite(writeData, outputStream);

         threadWrite.start();



      } catch (IOException e) {

         e.printStackTrace();

      } catch (InterruptedException e) {

         e.printStackTrace();

      }



   }



}

 

 

  1. 字符流示例代码:

 

import java.io.PipedReader;



import service.ReadData;



public class ThreadRead extends Thread {



   private ReadData read;

   private PipedReader input;



   public ThreadRead(ReadData read, PipedReader input) {

      super();

      this.read = read;

      this.input = input;

   }



   @Override

   public void run() {

      read.readMethod(input);

   }

}




import java.io.PipedWriter;



import service.WriteData;



public class ThreadWrite extends Thread {



   private WriteData write;

   private PipedWriter out;



   public ThreadWrite(WriteData write, PipedWriter out) {

      super();

      this.write = write;

      this.out = out;

   }



   @Override

   public void run() {

      write.writeMethod(out);

   }



}




public class ReadData {



   public void readMethod(PipedReader input) {

      try {

         System.out.println("read  :");

         char[] byteArray = new char[20];

         int readLength = input.read(byteArray);

         while (readLength != -1) {

            String newData = new String(byteArray, 0, readLength);

            System.out.print(newData);

            readLength = input.read(byteArray);

         }

         System.out.println();

         input.close();

      } catch (IOException e) {

         e.printStackTrace();

      }

   }

}




import java.io.IOException;

import java.io.PipedWriter;



public class WriteData {



   public void writeMethod(PipedWriter out) {

      try {

         System.out.println("write :");

         for (int i = 0; i < 300; i++) {

            String outData = "" + (i + 1);

            out.write(outData);

            System.out.print(outData);

         }

         System.out.println();

         out.close();

      } catch (IOException e) {

         e.printStackTrace();

      }

   }

}




import extthread.ThreadRead;

import extthread.ThreadWrite;

import service.ReadData;

import service.WriteData;



import java.io.IOException;

import java.io.PipedReader;

import java.io.PipedWriter;



public class Run {



   public static void main(String[] args) {



      try {

         WriteData writeData = new WriteData();

         ReadData readData = new ReadData();



         PipedReader pipedReader = new PipedReader();

         PipedWriter pipedWriter = new PipedWriter();



         // inputStream.connect(outputStream);

         pipedWriter.connect(pipedReader);



         ThreadRead threadRead = new ThreadRead(readData, pipedReader);

         threadRead.start();



         Thread.sleep(2000);



         ThreadWrite threadWrite = new ThreadWrite(writeData, pipedWriter);

         threadWrite.start();



      } catch (IOException e) {

         e.printStackTrace();

      } catch (InterruptedException e) {

         e.printStackTrace();

      }



   }



}

 

 

运行结果:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值