这些Java线程是否陷入僵局?

时间:2015-02-20 04:44:21

标签: java multithreading

我写了一个示例程序来说明使用管道是线程。我创建了2个帖子。

  1. Thread1正在发送“Hi this is thread1”并调用wait()以完成第2个线程。

  2. Thread2正在打印thread1发送的消息,并且还会附加到字符串缓冲区中,然后一旦收到整个消息,thread2将打印字符串缓冲区的内容并调用notify。现在调用wait()并通知两个线程往往处于死锁状态

  3. 奇怪的是,thread2打印了一条消息但没有打印字符串缓冲区的内容。

    package com.tuto.MultiThreading;
    
    import java.io.IOException;
    import java.io.PipedInputStream;
    import java.io.PipedOutputStream;
    
    public class PipeExample {
    
        public static void main(String[] args) throws IOException, InterruptedException {
            final Object obj=new Object();
            final PipedOutputStream pipeoutstream=new PipedOutputStream ();
            final PipedInputStream pipeinputstream=new PipedInputStream(pipeoutstream);
    
            Thread thread1= new Thread(new Runnable()
            {
    
                public void run() {
                    try {
                        pipeoutstream.write("Hello I am thread1".getBytes());
                        synchronized (obj) 
                        {
    
                            obj.wait(); 
                        }
    
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    finally
                    {
                        try {
                            pipeoutstream.close();
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }   
                    }
    
                }
    
            });
    
    
              Thread thread2 = new Thread(new Runnable() {
                    public void run() {
                        try {
    
                            int data = pipeinputstream.read();
                            StringBuffer sb=new StringBuffer();
                            while(data != -1){
                                System.out.print((char) data);
                                sb.append((char)data);
                                data = pipeinputstream.read();
                            }
                            System.out.println();
                            System.out.println(sb.toString());
                            synchronized (obj) {
    
                                obj.notify();
                            }
    
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        finally
                        {
                            try {
                                pipeinputstream.close();
                            } catch (IOException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }   
                        }
                    }
                });
    
            thread1.start();
            thread2.start();
            thread1.join();
            thread2.join();
            System.exit(1);
        }
    }
    

    OUTPUT :: 你好,我是thread1

    更新了决议:

    package com.tuto.MultiThreading;
    
    import java.io.IOException;
    import java.io.PipedInputStream;
    import java.io.PipedOutputStream;
    
    public class PipeExample {
    
        public static void main(String[] args) throws IOException, InterruptedException {
            final Object obj=new Object();
            final PipedOutputStream pipeoutstream=new PipedOutputStream ();
            final PipedInputStream pipeinputstream=new PipedInputStream(pipeoutstream);
    
            Thread thread1= new Thread(new Runnable()
            {
    
                public void run() {
                    try {
                        pipeoutstream.write("Hello I am thread1".getBytes());
    
    
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    finally
                    {
                        try {
                            pipeoutstream.close();
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }   
                        synchronized (obj) 
                        {
    
                            try {
                                obj.wait();
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }   
                        }
                    }
    
                }
    
            });
    
    
              Thread thread2 = new Thread(new Runnable() {
                    public void run() {
                        try {
    
                            int data = pipeinputstream.read();
                            StringBuffer sb=new StringBuffer();
                            while(data != -1){
                                System.out.print((char) data);
                                sb.append((char)data);
                                data = pipeinputstream.read();
                            }
                            System.out.println();
                            System.out.println(sb.toString());
                            synchronized (obj) {
    
                                obj.notify();
                            }
    
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        finally
                        {
                            try {
                                pipeinputstream.close();
                            } catch (IOException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }   
                        }
                    }
                });
    
            thread1.start();
            thread2.start();
            thread1.join();
            thread2.join();
            System.exit(1);
        }
    }
    

    现在我有点困惑了。我刚从try catch到最后移动了wait()。它是如何影响Pipestream阻塞的?

1 个答案:

答案 0 :(得分:2)

问题在于

data = pipeinputstream.read();
线程2中的

是阻塞调用。来自PipedInputStream#read()

的javadoc
  

此方法阻塞,直到输入数据可用,结束   检测到流,或抛出异常。

线程2一直等待,直到其中一件事发生。由于它们都不会发生,因此线程将无法notify另一个。

这不是死锁。

请注意,即使该调用未阻塞并返回-1,在线程1调用notify之前,线程2仍然可以执行其wait。在这种情况下,线程1将处于一个恒定的等待状态,你的程序将不会终止。