Java 线程详解(下)

导读:本篇文章讲解 Java 线程详解(下),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

一、线程生命周期

《详解操作系统进程》中,从操作系统层面介绍了进程(线程)的生命周期的变迁,在操作系统中,线程的状态主要包含了五种:初始化、等待状态、就绪状态、运行状态和终止状态

但在Java中,定义了六种状态的,其中RUNNABLE状态对应运行状态和就绪状态,而等待状态在Java中细分为三种BLOCKED、WAITING、TIMED_WAITING

关于这三种状态的描述,下面的源码中的注释已经解释的很清楚

BLOCKED状态对应于对象锁,某个线程竞争对象锁失败时就处于阻塞状态

WAITING状态对应于永久等待,如果没有被唤醒,将会处于永久等待的状态

TIMED_WAITING状态对应于超时等待,超过了等待的时间之后,它们就会被主动唤醒,然后处于RUNNABLE状态,等待CPU分配时间片

public enum State {

    NEW,
    RUNNABLE,
    /**
     * Thread state for a thread blocked waiting for a monitor lock.
     * A thread in the blocked state is waiting for a monitor lock
     * to enter a synchronized block/method or
     * reenter a synchronized block/method after calling
     * {@link Object#wait() Object.wait}.
     */
    BLOCKED,

    /**
     * <ul>
     *   <li>{@link Object#wait() Object.wait} with no timeout</li>
     *   <li>{@link #join() Thread.join} with no timeout</li>
     *   <li>{@link LockSupport#park() LockSupport.park}</li>
     * </ul>
     */
    WAITING,

    /**
     * <ul>
     *   <li>{@link #sleep Thread.sleep}</li>
     *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
     *   <li>{@link #join(long) Thread.join} with timeout</li>
     *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
     *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
     * </ul>
     */
    TIMED_WAITING,

    TERMINATED;
}

Java中这六种线程状态的生命周期,可以用下面的图来表示:

Java 线程详解(下));
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

System.out.println(“wait end …….”);
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

System.out.println(“wait end ……. “);
}
}
}).start();

new Thread(new Runnable() {
@Override
public void run() {
if (flag){
synchronized (lock){
if (flag){
lock.notify();
System.out.println(“notify …….”);
flag = false;
}

}
}
}
}).start();
}
}

注:wait于notify()必须结合synchronized关键字使用,否则会抛出IllegalMonitorStateException异常

等待唤醒机制的另一种实现是LockSupport,LockSupport是JDK中用来实现线程阻塞和唤醒的工具,线程调用park()方法则等待”许可“,调用unpark()方法则为指定线程提供”许可“。使用LockSupport的好处是,可以在任何场景使线程阻塞(不需要像wait()方法需要结合synchronized关键),并且不用担心阻塞和唤醒的顺序,但是要注意多次唤醒的效果和一次唤醒的效果一样

public class LockSupportTest {

    public static void main(String[] args) {
        Thread parkThread = new Thread(new ParkThread());
        parkThread.start();

        System.out.println("唤醒parkThread");
        LockSupport.unpark(parkThread);
    }

    static class ParkThread implements Runnable{

        @Override
        public void run() {
            System.out.println("ParkThread开始执行");
            LockSupport.park();
            System.out.println("ParkThread执行完成");
        }
    }
}

4.3 管道输入输出流

管道输入/输出流和普通文件输入/输出流或者网络输入/输出流的不同指出在于,它主要用于线程之间的数据传输,而传输的媒介为内存。管道输入/输出流主要包括如下四种具体实现:

PipedOutputStream、PipedInputStream、PipedReader和PipedWriter,前面两种面向字节,而后面两种面向字符

public class PipedTest {

    public static void main(String[] args) throws Exception {
        PipedWriter out = new PipedWriter();
        PipedReader in = new PipedReader();
        // 将输出流和输入流进行连接,否则在使用时会抛出IOException
        out.connect(in);

        Thread printThread = new Thread(new Print(in), "PrintThread");

        printThread.start();
        int receive = 0;
        try {
            while ((receive = System.in.read()) != -1) {
                out.write(receive);
            }
        } finally {
            out.close();
        }
    }

    static class Print implements Runnable {
        private PipedReader in;

        public Print(PipedReader in) {
            this.in = in;
        }

        @Override
        public void run() {
            int receive = 0;
            try {
                while ((receive = in.read()) != -1) {
                    System.out.print((char) receive);
                }
            } catch (IOException ex) {
            }
        }
    }
}

4.4 Thread.join()

join()方法可以理解为线程合并,将并行的线程通过join()方法合并成串行的,因为当前线程会一直阻塞等待调用join()方法的线程执行完毕才能继续执行(如果没有指定时间),所以join()方法的好处是可以保证线程的执行顺序,但是如果调用线程的join()方法其实已经失去了并行的意义,虽然存在多个线程,但这些线程本质上还是串行的。join()的实现也是基于等待唤醒机制的。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/112130.html

(0)
Java光头强的头像Java光头强

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!