五、睡眠和唤醒一个线程

  有时,你会想要在一段特定的时间后再去中断线程的运行。举个例子,程序中的一个线程每一分钟检查一次传感器的状态,剩余的时间,线程应该处于空闲的状态。在这段空闲时间里,线程不会使用计算机的任何资源。一分钟后,线程已经准备好了,才让JVM选择调用它继续执行。你可以使用 Thread 类的 sleep() 方法来达到此目的。该方法接受一个 int 类型参数表明线程挂起不运行的毫秒数。当睡眠时间结束,线程转移到可运行状态等待JVM的调度。

  TimeUnit 枚举类的某个成员同样具有 sleep() 方法。该方法利用了 Thread 类的 sleep() 方法,使得当前线程睡眠,但是它接受的参数的单位并不是固定为毫秒数,更加方便。

  在本秘诀中,我们开发一个利用 sleep() 方法每秒输出 Date 值的程序。

public class FileMain {
    public static void main(String[] args) {
        FileClock clock = new FileClock();
        Thread thread = new Thread(clock);
        thread.start();

        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        thread.interrupt();
    }
}

public class FileClock implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.printf("%s\n", new Date());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                System.out.printf("The FileClock has been interrupted");
            }
        }
    }

}

  当你调用 sleep() 方法时,线程就会放弃占用CPU和停止执行一段时间。在这段时间里,它不占用CPU时间。

  当线程在睡眠中并且被中断时,该方法立即抛出一个 InterruptedException 异常,并不会等待直到睡眠时间到达。

  注意:yield() 方法也具有让线程放弃占用CPU的功能,不过,这个方法最好只用来表明自己可以放弃CPU占用,JVM的规范中没有强制要求其必须要放弃CPU占用。这个方法一般只用在调试环境中,让具有更高权限的线程可以抢占执行。

  笔者总结:线程调用 sleep() 方法后,该线程处于挂起状态,自身不会去抢占CUP等资源来运行,但JVM内部有系统线程去感知是否该睡眠线程被中断,从而以抛出异常方式通知睡眠线程提前唤醒来运行代码处理此种情况。

六、等待线程的完成

  某些场景下,我们可能需要等待线程的终结。举个例子:我们的程序在顺序上可能需要在执行某些步骤之前需要初始化某些资源。我们可以把初始化资源的任务作为一个单独的线程运行,并且在主任务线程中等待它完成后再进行下一步的处理。

  我们可以使用 Thread 类的 join() 方法达到该目的。当我们调用一个 Thread 对象的 join() 方法时,调用此方法的线程就会挂起,直到 Thread 对象关联的线程执行完毕。

public class DataSourcesLoader implements Runnable{

    @Override
    public void run() {
        System.out.printf("Beginning data sources loading: %s\n",
                new Date());
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.printf("Data sources loading has finished: %s\n",
                new Date());
    }

}

public class Main {
    public static void main(String[] args) {
        DataSourcesLoader dsLoader = new DataSourcesLoader();
        Thread thread1 = new Thread(dsLoader, "DataSourceThread");

        NetworkConnectionsLoader ncLoader = new NetworkConnectionsLoader();
        Thread thread2 = new Thread(ncLoader, "NetworkConnectionLoader");

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.printf("Main: Configuration has been loaded: %s\n", new Date());
    }
}

public class NetworkConnectionsLoader implements Runnable{

    @Override
    public void run() {
        System.out.printf("Beginning Network connection: %s\n",
                new Date());
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.printf("Network connection has finished: %s\n",
                new Date());
    }

}

  如果你运行此示例程序多次后就会发现,每次都是先运行 thread1 并结束后,才运行 thread2,thread2结束后才会结束 main 线程的运行。

  join() 方法具有两个类似的方法,他们分别是:

    (A) join(long milliseconds)

    (B) join(long milliseconds, long nanos)

  这两个方法通向会挂起调用线程直到该方法所属的 Thread 对象关联的线程执行结束,但是在指定的时间达到后,调用线程可以继续运行,不用一直等待。

  笔者总结:这三个方法经常用来线程之间的同步,带参数的方法可以实现超时不等待逻辑。

重要:本系列翻译文档也会在本人的微信公众号(此山是我开)第一时间发布,欢迎大家关注。

Java 7 Concurrency Cookbook 翻译 第一章 线程管理之三的更多相关文章

  1. Java 7 Concurrency Cookbook 翻译 第一章 线程管理之一

    一.简介 在计算机的世界里,当我们谈论并发时,我们指的是一系列的任务同时运行于一个计算机中.这里说的同时运行,在计算机拥有多于一个处理器或者是一个多核处理器的时候才是真正的同时,在计算机只拥有单核处理 ...

  2. Java 7 Concurrency Cookbook 翻译 第一章 线程管理之六

    十一.处理线程组中的未控制异常 每种编程语言一个很重要的特性就是其所提供的用来处理程序中错误情况的机制.Java语言和其他的现代语言一样,是提供了异常机制来处理对象程序中的错误.Java提供了很多的类 ...

  3. Java 7 Concurrency Cookbook 翻译 第一章 线程管理之五

    九.使用线程本地变量 一个并发程序的最关键特征就是共享数据.这个特性在那些继承了 Thread 类或者 实现了 Runnable 接口的对象上显得更加重要. 如果你创建一个实现了 Runnable 接 ...

  4. Java 7 Concurrency Cookbook 翻译 第一章 线程管理之四

    七.创建和运行一个后台线程 Java中有一种特别的线程叫做 deamon(后台) 线程.这类线程具有非常低的权限,并且只有在同一个程序中没有其他的正常线程在运行时才会运行.注意:当一个程序中只剩下后台 ...

  5. Java 7 Concurrency Cookbook 翻译 第一章 线程管理之二

    三.中断一个线程 一个拥有多个线程的Java程序要结束,需要满足两个条件之一:一是所有的非后台线程都执行结束了:二是某个线程执行了 System.exit() 方法.当你想要终结一个运行中的Java程 ...

  6. Java 7 Concurrency Cookbook 翻译 序言

    在日常的Java代码开发过程中,很难免地有对多线程的需求,掌握java多线程和并发的机制也是Java程序员写出更健壮和高效代码的基础.笔者找寻国内已出版的关于Java多线程和并发的的中文书籍和翻译书籍 ...

  7. java的优点和误解 《java核心技术卷i》第一章

    <java核心技术卷i>第一章主要内容包括三点: 1:Java白皮书的关键术语:描述Java的十一个关键字: 2:Java applet 3 :关于Java的常见误解   1:第一章:Ja ...

  8. java JDK8 学习笔记——第11章 线程和并行API

    第11章 线程与并行API 11.1 线程 11.1.1 线程 在java中,如果想在main()以外独立设计流程,可以撰写类操作java.lang.Runnable接口,流程的进入点是操作在run( ...

  9. Java 螺纹第三版 第一章Thread介绍、 第二章Thread创建和管理学习笔记

    第一章 Thread导论 为何要用Thread ? 非堵塞I/O      I/O多路技术      轮询(polling)      信号 警告(Alarm)和定时器(Timer) 独立的任务(Ta ...

随机推荐

  1. C#------对SQLServer进行简单的增,删,改,查

    EF中的操作转载: http://www.cnblogs.com/mcgrady/archive/2015/03/21/4355282.html PSContext db = new PSContex ...

  2. ci查询数据库

    public function getUsers() { $this->load->database();//载入数据库 $users = $this->db->get(&qu ...

  3. 9月22日下午JavaScript----Document对象

    document对象 一.找元素 1.根据id找 示例: <input id = "a" type="button" value="找元素&qu ...

  4. Java——URL和URLConnection

    使用URL读取内容 import java.awt.im.InputContext; import java.io.InputStream; import java.net.MalformedURLE ...

  5. Java关键字——final

    final在Java中表示的意思是最终,使用final关键字声明类属性.方法,注意: 1.使用final声明的类不能有子类 2.使用final声明的方法不能被子类所覆写 3.使用final声明的变量即 ...

  6. Java Web学习笔记-Servle生命周期

    Servlet会在服务器启动或第一次请求该Servlet的时候开始生命周期,在服务器停止的时候结束生命周期. 无论请求多少次Servlet,最多只有一个Servlet实例.多个客户端并发请求Servl ...

  7. DX9资源管理

    http://www.cnblogs.com/cxrs/archive/2013/04/03/D3DResourceManager.html http://kasicass.blog.163.com/ ...

  8. lazyload.js实现图片异步载入

    所谓图片异步加载,意思是不用一次把图片全部加载完,你可以叫它延迟加载,缓冲加载都行. 看看你有没有这种需求:某篇文章图片很多,如果在载入文章时就载入所有图片,无疑会延缓载入速度,让用户等更久,所以,我 ...

  9. C# 常用分页

    var num = TCalcPager.CalcPageCount(addList.Count, TDefautValue.PageSize); ; i < num; i++) { var r ...

  10. mysql 分页性能优化

    最简单的分页方法是这样的 , 该表中存在5w左右数据 执行时间平均在10s左右,因此该种方式在数据量大的情况下查询效率极低. 优化方式有以下几种 1.此种方式平均在7-8s之间(CreateDate ...