Java线程Thread(三)

来源:互联网 发布:mysql qq充值 编辑:程序博客网 时间:2024/03/29 03:00

1,  Java线程间通信的方式有好多种,包括:

a)       管道(Pipe):可用于同一个进程间的多个线程间数据通信。

b)       命名管道(named pipe):通过文件系统实现线程间数据通信,可以实现不同进程间的数据通信。

c)       共享内存:多个进程间访问同一个内存空间,需要通过信号量实现同步与互斥。

d)       内存映射(mapped memory):内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间来实现它。

e)       信号量(semaphore):主要用来实现线程间同步的手段。

f)        套接字(Socket):可以实现不同机器间的进程间的通信。

2,  通过管道的方法实现线程间通信,如下:

public classPipe {   public static void main(String args[]) throws Exception{      PipedInputStreamin = new PipedInputStream();      PipedOutputStreamout= newPipedOutputStream(in);      Senders = new Sender(out);      Receiverr = new Receiver(in);      Threadt1 = new Thread(s);      Threadt2 = new Thread(r);      t1.start();      t2.start();      t2.join();   }}class Sender implements Runnable {   OutputStreamout;   public Sender(OutputStream out) {      this.out = out;   }   public void run() {      for(int i = 0; i < 10; i++){         try {            out.write(i);            System.out.println("sender:"+i);         }catch(IOException e) {         }      }      try {         out.close();      }catch(IOException e) {      }   }}class Receiver implements Runnable {   InputStreamin;   public Receiver(InputStream in) {      this.in = in;   }   public void run() {      int value;      try {         while((value = in.read()) != -1){            System.out.println("receive:"+value);         }      }catch(IOException e) {      }   }}


以上通过PipedInputStream和PipedOutputStream输入输出管道实现线程t1,t2之间数据通信。

3,  通过共享变量实现线程间通信,如下:

public classFlag {   public static void main(String[] args) throws Exception {      FlagSenders = new FlagSender();      FlagReceiverr = new FlagReceiver(s);      Threadt1 = new Thread(s);      Threadt2 = new Thread(r);      t1.start();      t2.start();      t2.join();   }}class FlagSender implements Runnable {   volatile int value;   volatile boolean isValid;   public void run() {      for(int i = 0; i < 5; i++){         while(isValid){            Thread.yield();         }         value = (int)(Math.random()*256);         System.out.println("sender:"+value);         isValid = true;      }   }}class FlagReceiver implements Runnable {   FlagSendersender;   public FlagReceiver(FlagSendersender){      this.sender = sender;   }   public void run() {      while(true){         while(!sender.isValid){            Thread.yield();         }         System.out.println("receive:"+sender.value);         sender.isValid = false;      }   }}


如上,FlagSender中变量用关键字volatile,因为java虚拟机会对变量进行优化,变量值被修改后可能只是存储在当前线程的缓存中,而没有到主内存中。通volatile变量告诉虚拟机,该变量每次的改变都是修改的主内存中的值。通过Thread.yield();表示让当前线程让出CPU,然后再加入线程队伍一起竞争下一次CPU的使用权。

以上程序固然可以,但是由于while语句会造成CPU极大的浪费。可以通过Java 的Object对象的两个本地函数wait()和notify()进行优化,如下:

public classWFlag {   public static void main(String[] args) throws Exception {      WFlagSenders = new WFlagSender();      WFlagReceiver r = new WFlagReceiver(s);      Threadt1 = new Thread(s);      Threadt2 = new Thread(r);      t2.setDaemon(true);      t1.start();      t2.start();      t2.join();      try {         t1.join();         while (s.isValid) {            Thread.sleep(1000);         }      }catch(Exception e) {      }   }}class WFlagSender implements Runnable {   volatile int value;   volatile boolean isValid;    public void run() {      for (int i = 0; i < 5; i++) {         synchronized (this) {            while (isValid) {                try {                   this.wait();                }catch(InterruptedException e) {                }            }         }         value = (int) (Math.random()* 256);         System.out.println("sender:"+ value);         synchronized (this) {            this.notify();            isValid = true;         }      }   }}class WFlagReceiverimplementsRunnable {   WFlagSendersender;   publicWFlagReceiver(WFlagSender sender) {      this.sender = sender;   }   public void run() {      while (true) {         synchronized (sender) {            while (!sender.isValid) {                try {                   sender.wait();                }catch(InterruptedException e) {                }            }         }         System.out.println("receive:"+ sender.value);         synchronized (sender) {            sender.isValid = false;            sender.notify();         }      }   }}


以上

a)        wait()、notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写。

b)        调用某个对象的wait()方法能让当前线程阻塞,并且当前线程必须拥有此对象的monitor(即锁)。

c)        调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程,如果有多个线程都在等待这个对象的monitor,则只能唤醒其中一个线程。

d)        调用notifyAll()方法能够唤醒所有正在等待这个对象的monitor的线程。

0 0
原创粉丝点击