<address id="xhxt1"><listing id="xhxt1"></listing></address><sub id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></sub>

    <thead id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></thead>

    线程管理(七)守护线程的创建和运行

    声明:本文是《 Java 7 Concurrency Cookbook 》的第一章, 作者: Javier Fernández González 译者:郑玉婷 校对:方腾飞

    守护线程的创建和运行

    Java有一种特别的线程叫做守护线程。这种线程的优先级非常低,通常在程序里没有其他线程运行时才会执行它。当守护线程是程序里唯一在运行的线程时,JVM会结束守护线程并终止程序。

    根据这些特点,守护线程通常用于在同一程序里给普通线程(也叫使用者线程)提供服务。它们通常无限循环的等待服务请求或执行线程任务。它们不能做重要的任务,因为我们不知道什么时候会被分配到CPU时间片,并且只要没有其他线程在运行,它们可能随时被终止。JAVA中最典型的这种类型代表就是垃圾回收器。

    在这个指南中, 我们将学习如何创建一个守护线程,开发一个用2个线程的例子;我们的使用线程会写事件到queue, 守护线程会清除queue里10秒前创建的事件。

    准备

    指南中的例子是使用Eclipse IDE 来实现的。如果你使用Eclipse 或者其他的IDE,例如NetBeans, 打开并创建一个新的java项目。

    怎么做呢

    按照这些步骤来实现下面的例子:

    1.? ?创建 Event 类. 这个类只是用来储存我们程序里的工作的事件信息。声明2个属性,一个是java. util.Date 类型的 date 和另一个是String 类型的event 。并生成它们的读值和写值方法。

    2.? ?创建 WriterTask 类并实现Runnable接口。

    public class WriterTask implements Runnable {
    

    3.? ?声明queue,储存事件并实现类的构造函数,初始化queue。

    private Deque<Event> deque;
    public WriterTask (Deque<Event> deque){
    this.deque=deque;
    }

    4.? ?实现这个任务的 run() 方法 。 此方法有100个循环。在每个循环中我们会创建 一个Event对象,并保存到 queue里, 然后休眠1秒。

    @Override
    public void run() {
    for (int i=1; i<100; i++) {
       Event event=new Event();
       event.setDate(new Date());
       event.setEvent(String.format("The thread %s has generated an   event",Thread.currentThread().getId()));
       deque.addFirst(event);
       try {
          TimeUnit.SECONDS.sleep(1);
       } catch (InterruptedException e) {
          e.printStackTrace();
       }
     }
    }
    

    5.? ?创建 CleanerTask 类并一定扩展Thread类。

    public class CleanerTask extends Thread {
    

    6.? ?声明 queue,储存事件并实现类的构造函数,初始化queue,在这个构造函数,用setDaemon() 方法让此线程成为守护线程。

    private Deque<Event> deque;
    public CleanerTask(Deque<Event> deque) {
    this.deque = deque;
    setDaemon(true);
    }

    7.?? 实现run()方法。它是无限循环来获取当前日期并调用 clean() 方法.

    @Override
    public void run() {
     while (true) {
       Date date = new Date();
       clean(date);
     }
    }

    8.? ?实现 clean() 方法. 它获取最后的事件,如果它在10秒前被创建,就删除它并查看下一个事件。如果一个事件被删除,它会写一个事件信息和queue的新的大小,为了让你看到变化过程。

    private void clean(Date date) {
      long difference;
      boolean delete;
      if (deque.size()==0) {
        return;
      }
      delete=false;
      do {
        Event e = deque.getLast();
        difference = date.getTime() - e.getDate().getTime();
        if (difference > 10000) {
         System.out.printf("Cleaner: %s\n",e.getEvent()); deque.removeLast();
         delete=true;
        }
      } while (difference > 10000);
      if (delete){
       System.out.printf("Cleaner: Size of the queue: %d\n",deque. size());
      }
    }

    9.? ?现在实现主类。 创建一个类名为 Main 和 main() 方法。

    public class Main {
    public static void main(String[] args) {
    

    10. 创建使用 Deque 类的queue 来保存事件。

    Deque<Event> deque=new ArrayDeque<Event>();

    11. 创建 和开始3个 WriterTask 线程和一个 CleanerTask.

    WriterTask writer=new WriterTask(deque);
    for (int i=0; i<3; i++){
    Thread thread=new Thread(writer);
    thread.start();
    }
    CleanerTask cleaner=new CleanerTask(deque);
    cleaner.start();
    

    12. 运行程序查看结果。

    它是怎么工作的

    如果分析这个程序的输出,你可以发现queue可以一直增加直到它有30个事件,然后它的大小会在27-30之间直到运行结束。

    程序开始时有3个 WriterTask 线程。每个线程写一个事件然后休眠1秒。10秒之后,我们有30个事件在queue里。在这10秒内,当3个 WriterTask 线程休眠时, CleanerTasks已经开始运行,但是它没有删除任何事件,因为所有事件都才生成不到10秒。在剩下的运行里,CleanerTask 每秒删除3个事件, 然而3个 WriterTask 线程会另写3个,所以queue的大小在27-30之间。

    你可以修改 WriterTask 线程的休眠时间。如果你使用一个较小的值,你会发现CleanerTask 被分配到 CPU 时间片会更少,由于 CleanerTask 没有删除任何事件,所以queue大小会一直增加。

    更多

    只能在start() 方法之前可以调用 setDaemon() 方法。一旦线程运行了,就不能修改守护状态。

    可以使用 isDaemon() 方法来检查线程是否是守护线程(方法返回 true) 或者是使用者线程 (方法返回 false)。

    原创文章,转载请注明: 转载自并发编程网 – www.gofansmi6.com本文链接地址: 线程管理(七)守护线程的创建和运行


    FavoriteLoading添加本文到我的收藏
    • Trackback 关闭
    • 评论 (15)
      • Snway
      • 2013/08/27 9:39上午

      步骤1的代码呢?

      • 原文就没有的。

          • 郑玉婷
          • 2013/08/27 12:40下午

          原文没有哈。
          是这样吧:

          public class Event
          {
          private java.util.Date date;
          private String event;
          //然后用eclipse 自动生成读写值方法即可吧。
          }
          原文没有提到要生成类的构造函数,应该是必须的吧?无参数的构造函数。:)

      • keyganker
      • 2013/09/24 4:11下午

      刚才是个玩笑。。。我先说的是这么好的网站,还有这么好的人儿来分享国外优秀的技术文章,真是感谢!

      • .
      • 2014/02/15 10:09下午

      多线程使用ArrayDeque不会有问题么?

      • cha_bill
      • 2014/10/10 5:48下午

      翻译的很牵强.

      • cha_bill
      • 2014/10/10 5:49下午

      感觉像是走流水账一样!这是为了刷出名么!

      • superzero
      • 2016/11/10 10:49上午

      package Thread;

      import java.util.ArrayDeque;
      import java.util.Date;
      import java.util.Deque;
      import java.util.concurrent.TimeUnit;

      public class T7 {
      public static void main(String[] args) {
      Deque arrayDeque = new ArrayDeque();
      Task task = new Task(arrayDeque);
      for (int i = 0; i < 3; i++) {
      Thread thread = new Thread(task);
      thread.start();
      }
      ClearTask clearTask = new ClearTask(arrayDeque);
      clearTask.start();
      }
      }

      class ClearTask extends Thread {
      private Deque deque;
      public ClearTask(Deque deque) {
      this.deque = deque;
      setDaemon(false);
      }
      public void run() {
      while(true) {
      clean(new Date());
      }
      }
      private void clean(Date date) {
      long diff;
      boolean del;
      //System.out.println(“…”);
      if(deque.size() == 0) {
      return;
      }
      del = false;
      do {
      Event last = deque.getLast();
      diff = date.getTime() – last.getDate().getTime();
      System.out.println(diff + “…”);
      if(diff > 10000) {
      System.out.println(“clear:” + last.getEvent());
      deque.removeLast();
      del = true;
      }
      } while (diff > 10000);

      if(del) {
      System.out.println(“size:” + deque.size());
      }
      }
      }

      class Task implements Runnable{
      private Deque deque;
      public Task(Deque deque) {
      this.deque = deque;
      }
      public void run() {
      for (int i = 0; i < 100; i++) {
      Event event = new Event();
      event.setDate(new Date());
      event.setEvent(String.format("The thread %s has generated an event", Thread.currentThread().getId()));
      deque.addFirst(event);
      try {
      TimeUnit.MILLISECONDS.sleep(1000);
      } catch (InterruptedException e) {
      e.printStackTrace();
      }
      }
      }
      }

      class Event {
      private Date date;
      private String event;
      public Date getDate() {
      return date;
      }
      public void setDate(Date date) {
      this.date = date;
      }
      public String getEvent() {
      return event;
      }
      public void setEvent(String event) {
      this.event = event;
      }
      public String toString() {
      return "data:" + date.toLocaleString() + "event:" + event;
      }
      }

      这是我抄的例子,很奇怪,我在守护线程中添加System.out.println(diff + "…");,想打印出每次计算的时间,但是没有打印出来。
      于是我在boolean del;后添加了System.out.println("…");,结果上面计算的时间在控制台打印了出来。
      如果上面两个输出语句都注释的话,10秒过后根本也没有System.out.println("clear:" + last.getEvent());在控制台输出内容。
      是我哪里出问题了吗,帮忙看看?

        • cu chulainn
        • 2018/04/09 4:06下午

        main类 把Deque改成 Queue deque=new ArrayBlockingQueue(1000);就可以了

    您必须 登陆 后才能发表评论

    return top

    爱投彩票 hrz| 1nb| fbb| hv1| dhj| z1p| vfj| 1th| nr1| ztv| v0n| tht| d0v| hdh| 0lp| tpd| fr0| rvx| j0z| pdz| 1xn| tz9| tvj| j9d| lxt| 9jl| zl9| frz| v9b| p0r| xxz| 0zp| nx0| nhz| f8f| bpr| 8hd| vj8| nrt| fj9| htp| h9d| l9f| vrj| 9nj| zf7| hjd| z7z| bvp| 8dx| bl8| rnn| p8h| zpr| 8fp| 8dx| pd8| ntb| n7z| xrl|