JAVA 并发编程之守护线程的创建与运行

java里有一种特殊的线程叫做守护线程(Daemon)线程。这种线程的优先级很低,通常来说,当同一个应用程序里没有其他的线程运行的时候,守护线程才运行。当程序中唯一运行的的线程是守护线程时,并且守护线程执行结束后 ,JVM也就结束了这个程序。

因为这种特性,守护线程通常被用来作为同一程序中普通线程(用户线程)的服务提供者。它们通常是无线循环的,以等待服务请求或者执行线程的任务。它们不能做重要工作,因为我们不可能知道守护线程什么时候获取CPU时钟,并且,在没有其他线程运行时,守护线程随时可以结束。典型应用就是JAVA GC。

如何创建守护线程,写一个简单的DEMO。场景如下:有两线程,一种是用户线程,它将事件写到一个队列中。另一个是守护线程。他将管理这个队列。如果生成的事件超过10秒钟,就会被移除。

1.创建一个Event类。在类中声明两个私有属性,一个日期类型属性date;另一个字符串类型的属性event.并生成这两个属性的读写方法。

public 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;
    }

2.创建WriterTask类,用以实现Runnable接口。

public class WriterTask implements Runnable{}

3.声明一个存放Event对象的队列,并实现带参数的构造器,来初始化这个队列对象。

Deque<Event> deque;

public WriterTask(Deque<Event> deque) {
        this.deque = deque;
    }
   4.实现线程的run()方法。它将执行100次循环。在每次循环中,都会创建一个新的Event对象,并放入队列中。然后休眠一秒钟。

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.SECONDS.sleep(1);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    }

5.创建CleanerTask类并继承Thrad类。

public class CleanerTask extends Thread{}

6.声明存放Event对象的队列,并实现构造器,来初始化这个队列对象。同时,在这个构造器中,通过setDaemon()方法把这个线程设置为守护线程。
       Deque<Event> deque;
       public CleanerTask(Deque<Event> deque) {
          this.deque = deque;
          setDaemon(true);
    }

7.实现run()方法,它会无限制的重复运行,在每次运行中,将获取当前的时间,并调用clean()方法。

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

8.实现clean()方法。clean()方法将读取队列的最后一个事件对象,如果这个事件是10秒种前创建的,就将它删除并且检查下一个。如果有事件被删除,clean()讲打印被删除事件信息,讲打印队列长度。

public void clean(Date date){
        long diffrence;
        boolean delete;
        if(deque.size()==0){
            return;
        }
        delete=false;
        do{
            Event e=deque.getLast();
            diffrence=date.getTime()-e.getDate().getTime();
            if(diffrence>10000){
                System.out.printf("Cleaner:%s\n",e.getEvent());
                deque.removeLast();
                delete=true;
            }
        }while(diffrence>10000);
        if(delete){
            System.out.printf("Cleaner: Size of the queue: %d\n",deque.size());
   }
   
   }public void clean(Date date){
        long diffrence;
        boolean delete;
        if(deque.size()==0){
            return;
        }
        delete=false;
        do{
            Event e=deque.getLast();
            diffrence=date.getTime()-e.getDate().getTime();
            if(diffrence>10000){
                System.out.printf("Cleaner:%s\n",e.getEvent());
                deque.removeLast();
                delete=true;
            }
        }while(diffrence>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,用来存放事件。

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

11.创建三个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.运行,查看结果。发现,队列对象会不断增长到30个,然后到程序结束,队列长度维持在27-30之间,

时间: 2024-12-24 09:33:59

JAVA 并发编程之守护线程的创建与运行的相关文章

Java并发编程(01):线程的创建方式,状态周期管理

本文源码:GitHub·点这里 || GitEE·点这里 一.并发编程简介 1.基础概念 程序 与计算机系统操作有关的计算机程序.规程.规则,以及可能有的文件.文档及数据. 进程 进程是计算机中的程序,关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体:在面向线程设计的计算机结构中,进程是线程的容器.程序是指令.数据及其组织形式的描述,进程是程序的实体. 线程 线程是操作系统能够进行运算调度的最小单

Java并发学习之七——守护线程

本文是学习网络上的文章时的总结,感谢大家无私的分享. 1.Java有两种Thread:"守护线程Daemon"与"用户线程User".用户线程:Java虚拟机在它所有非守护线程已经离开后自动离开:守护线程:则是用来服务用户线程的,如果没有其他用户线程在运行,那么就没有可服务对象,也就没有理由继续下去. 2.setDaemon(boolean on)方法可以方便的设置线程的Daemon模式,true为Daemon模式,此方法必须在线程启动之前调用,当线程正在运行时调用

【java并发编程实战】-----线程基本概念

学习Java并发已经有一个多月了,感觉有些东西学习一会儿了就会忘记,做了一些笔记但是不系统,对于Java并发这么大的"系统",需要自己好好总结.整理才能征服它.希望同仁们一起来学习Java并发编程,共同进步,互相指导. 在学习Java并发之前我们需要先理解一些基本的概念:共享.可变.线程安全性.线程同步.原子性.可见性.有序性. 共享和可变 要编写线程安全的代码,其核心在于对共享的和可变的状态进行访问. "共享"就意味着变量可以被多个线程同时访问.我们知道系统中的资

Java并发编程系列(一)-线程的基本使用

最近在学习java并发编程基础.一切从简,以能理解概念为主. 并发编程肯定绕不过线程.这是最基础的. 那么就从在java中,如何使用线程开始. 继承Thread类 继承Thread类,重写run方法,new出对象,调用start方法. 在新启的线程里运行的就是重写的run方法. 1 /** 2 * 集成Thread类 实现run() 3 */ 4 public class C1 extends Thread { 5 6 @Override 7 public void run() { 8 try

Java7并发编程实战(一) 守护线程的创建和运行

Java里有一种特殊的线程叫做守护(Daemon)线程,这种线程的优先级很低,通常来说,当一个应用程序里面没有其他线程运行的时候,守护线程才运行,当线程是程序中唯一运行的线程时,守护线程执行结束后,JVM也就结束了这个程序.因此,守护线程通常被用来作为同一程序中普通线程的服务提供者,通常是无线循环的,以等待服务请求或者线程任务. 代码实现 1:创建Event类,声明两个私有属性 package com.packtpub.java7.concurrency.chapter1.recipe7.eve

Java并发编程(02):线程核心机制,基础概念扩展

本文源码:GitHub·点这里 || GitEE·点这里 一.线程基本机制 1.概念描述 并发编程的特点是:可以将程序划分为多个分离且独立运行的任务,通过线程来驱动这些独立的任务执行,从而提升整体的效率.下面提供一个基础的演示案例. 2.应用案例 场景:假设有一个容器集合,需要拿出容器中的每个元素,进行加工处理,一般情况下直接遍历就好,如果数据偏大,可以根据线程数量对集合切割,每个线程处理一部分数据,这样处理时间就会减少很多. public class ExtendThread01 { publ

Java并发编程-如何终止线程

我们知道使用stop().suspend()等方法在终止与恢复线程有弊端,会造成线程不安全,那么问题来了,应该如何正确终止与恢复线程呢?这里可以使用两种方法: 1.使用interrupt()中断方法. 2.使用volatile boolean变量进行控制. 在使用interrupt方法之前,有必要介绍一下中断以及与interrupt相关的方法.中断可以理解为线程的一个标志位属性,表示一个运行中的线程是否被其他线程进行了中断操作.这里提到了其他线程,所以可以认为中断是线程之间进行通信的一种方式,简

并发编程专题(二)-线程的创建方式

1.创建多线程几种方式 1.1 继承Thread,重写父类的run()方法 Java使用java.lang.Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例.每个线程的作用是完成一定的任务,实际上就是执行一段程序流即一段顺序执行的代码.Java使用线程执行体来代表这段程序流.Java中通过继承Thread类来创建并启动多线程的步骤如下: 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程

JAVA - 并发编程 - 执行器和线程池

思考? 1 为什么要使用执行器和线程池? 2 执行器和线程是什么?怎么使用 执行器 线程执行器分离了任务的创建和执行,提高了线程的性能 线程池 避免了频繁地创建和销毁线程,达到线程对象的重用,可以根据项目灵活地控制并发的数量 ExecutorService (java.util.concurrent) 1 Executors.newCachedThreadPool() 可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程 2 Executors.newFixedT