Java 7 Concurrency Cookbook 翻译 第一章 线程管理之四
七、创建和运行一个后台线程
Java中有一种特别的线程叫做 deamon(后台) 线程。这类线程具有非常低的权限,并且只有在同一个程序中没有其他的正常线程在运行时才会运行。注意:当一个程序中只剩下后台线程时,JVM会终结所有的后台线程并结束程序。
由于这个特性,后台线程一般用于为同一个程序中的其他正常线程提供服务。这种后台线程一般都有一个无限的循环在等待请求服务或者执行请求的任务。由于不知道它们何时可以获得CPU的调用执行,同时在没有其他正常线程的情况下会被JVM终结,所以后台线程不能用于执行重要的任务。后台线程的一个典型应用是Java中的垃圾回收器。
本秘诀中,我们将学习如何创建具有两个线程的程序:一个正常线程在一个队列上写事件,另一个后台线程负责清理该队列上10秒之前生成的事件。
public class CleanerTask extends Thread {
private Deque<Event> deque;
public CleanerTask(Deque<Event> deque) {
this.deque = deque;
setDaemon(true);
}
@Override
public void run() {
while (true) {
Date date = new Date();
clean(date);
}
}
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 > 1000) {
System.out.println("Cleaner: "+ e.getEvent() +"\n");
deque.removeLast();
delete = true;
}
} while (difference > 1000);
if (delete) {
System.out.printf("Cleaner: Size of the queue: "+ deque.size() +"\n");
}
}
}
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;
}
}
public class Main {
public static void main(String[] args) {
Deque<Event> deque = new ArrayDeque<Event>();
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();
}
}
public class WriterTask implements Runnable{
private Deque<Event> deque;
public WriterTask(Deque<Event> deque) {
this.deque = deque;
}
@Override
public void run() {
for (int i = 1; i < 20; 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();
}
}
}
}
注意:setDeamon() 方法必须在 start() 方法前调用才有效。一旦线程启动,就不能修改其是否为后台线程了。同时,可以使用 isDeamon() 方法来判断线程是否为后台线程。
八、处理线程中未控制的异常
Java中有两类异常:
(A) 检测异常:必须捕获或者抛出。
(B) 不检测异常:可以不捕获。
因为 Thread 对象的 run() 方法不能抛出异常,所以出现在此方法中的检测异常都必须捕获。当 run() 方法中抛出不检测异常时,Thread 对象的默认行为是写线程堆栈信息到控制台,然后退出程序。
幸运的是,Java提供了让我们可以捕获和转换未检测异常的机制,使得我们可以避免由于 run() 方法中异常的抛出而导致的程序终结。
Java中有一个 UncaughtExceptionHandler 接口来处理未捕获的异常。
public class ExceptionHandler implements UncaughtExceptionHandler{
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("An exception has been captured");
System.out.println("Thread: " + t.getId());
System.out.println("Exception: " + e.getClass().getName() + ": "
+ e.getMessage());
System.out.println("Stack Trace: ");
e.printStackTrace(System.out);
System.out.println("Thread status: " + t.getState());
}
}
public class Main {
public static void main(String[] args) {
Task task = new Task();
Thread thread = new Thread(task);
thread.setUncaughtExceptionHandler(new ExceptionHandler());
thread.start();
}
}
public class Task implements Runnable {
@Override
public void run() {
Integer.parseInt("TTT");
}
}
当线程中有一个异常抛出来时,JVM首先检查该线程是否有设置线程异常处理器,如果有就调用该处理器处理该异常。如果没有,JVM的默认行为是打印线程堆栈信息到控制台,同时推出程序。
注意:Thread 类有一个静态方法 setDefaultUncaughtExceptionHandler() 来为程序中所有的未捕获异常设置处理器。当线程中抛出一个未捕获的异常时:JVM首先查看该线程是否有设置对应的线程异常处理器,如果没有再查看线程所属的线程组是否有设置好线程异常处理器,如果还没有再查看程序是否有设置默认线程异常处理器。
如果没有任何异常处理器存在,JVM就会执行默认行为:写线程栈帧信息到控制台,终止程序的运行。
重要:本系列翻译文档也会在本人的微信公众号(此山是我开)第一时间发布,欢迎大家关注。
Java 7 Concurrency Cookbook 翻译 第一章 线程管理之四的更多相关文章
- Java 7 Concurrency Cookbook 翻译 第一章 线程管理之一
一.简介 在计算机的世界里,当我们谈论并发时,我们指的是一系列的任务同时运行于一个计算机中.这里说的同时运行,在计算机拥有多于一个处理器或者是一个多核处理器的时候才是真正的同时,在计算机只拥有单核处理 ...
- Java 7 Concurrency Cookbook 翻译 第一章 线程管理之六
十一.处理线程组中的未控制异常 每种编程语言一个很重要的特性就是其所提供的用来处理程序中错误情况的机制.Java语言和其他的现代语言一样,是提供了异常机制来处理对象程序中的错误.Java提供了很多的类 ...
- Java 7 Concurrency Cookbook 翻译 第一章 线程管理之五
九.使用线程本地变量 一个并发程序的最关键特征就是共享数据.这个特性在那些继承了 Thread 类或者 实现了 Runnable 接口的对象上显得更加重要. 如果你创建一个实现了 Runnable 接 ...
- Java 7 Concurrency Cookbook 翻译 第一章 线程管理之二
三.中断一个线程 一个拥有多个线程的Java程序要结束,需要满足两个条件之一:一是所有的非后台线程都执行结束了:二是某个线程执行了 System.exit() 方法.当你想要终结一个运行中的Java程 ...
- Java 7 Concurrency Cookbook 翻译 第一章 线程管理之三
五.睡眠和唤醒一个线程 有时,你会想要在一段特定的时间后再去中断线程的运行.举个例子,程序中的一个线程每一分钟检查一次传感器的状态,剩余的时间,线程应该处于空闲的状态.在这段空闲时间里,线程不会使用计 ...
- Java 7 Concurrency Cookbook 翻译 序言
在日常的Java代码开发过程中,很难免地有对多线程的需求,掌握java多线程和并发的机制也是Java程序员写出更健壮和高效代码的基础.笔者找寻国内已出版的关于Java多线程和并发的的中文书籍和翻译书籍 ...
- java的优点和误解 《java核心技术卷i》第一章
<java核心技术卷i>第一章主要内容包括三点: 1:Java白皮书的关键术语:描述Java的十一个关键字: 2:Java applet 3 :关于Java的常见误解 1:第一章:Ja ...
- java JDK8 学习笔记——第11章 线程和并行API
第11章 线程与并行API 11.1 线程 11.1.1 线程 在java中,如果想在main()以外独立设计流程,可以撰写类操作java.lang.Runnable接口,流程的进入点是操作在run( ...
- Java 螺纹第三版 第一章Thread介绍、 第二章Thread创建和管理学习笔记
第一章 Thread导论 为何要用Thread ? 非堵塞I/O I/O多路技术 轮询(polling) 信号 警告(Alarm)和定时器(Timer) 独立的任务(Ta ...
随机推荐
- POJ2187Beauty Contest(任意点的最远距离 + 凸包)
题目链接 题意:就是给N个点的坐标,然后求任意两个点距离的平方最大的值 枚举超时. 当明白了 最远距离的两个点一定在凸包上,一切就好办了.求出凸包,然后枚举 #include <iostream ...
- Setting up Django and your web server with uWSGI and nginx
https://uwsgi.readthedocs.io/en/latest/tutorials/Django_and_nginx.html Setting up Django and your we ...
- php适配器设计模式
<?php //适配器模式 //服务器端代码 class tianqi{ public static function show(){ $today= array('tep' =>28 , ...
- OC面向对象特性: 继承
基础知识 1.标识符是有字母,数字,下划线组成的. 2.首字母只能是字母,下划线,不能为数字. 3.标识符要做到见名之意. 4.标识符不能使用已定义的关键字和预定义标识符. 继承 继承:子类可以直接访 ...
- JavaWeb文件下载,提示用户保存而不是让浏览器直接打开
1.通过HttpServletResponse对象实现文件下载 服务端向客户端游览器发送文件时,如果是浏览器支持的文件类型,一般会默认使用浏览器打开,比如txt.jpg等,会直接在浏览器中显示,如果需 ...
- codeforces 709B Checkpoints
题目链接:http://codeforces.com/problemset/problem/709/B 题目大意: 第一行给出两个数 n,x.第二行 输入 n 个数. 要求:从x位置遍历 n-1 个位 ...
- VS编译器从DLL导出模板类
DLL与模板 http://msdn.microsoft.com/en-us/library/twa2aw10.aspx http://www.codesynthesis.com/~boris/blo ...
- css div垂直居中
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 创建守护进程步骤与setsid() -- linux deamon进程
原创:http://www.cnblogs.com/mickole/p/3188321.html 一,守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终端并且 ...
- Memcached【Magent+Memcached】集群
Memcached介绍 事件处理libevent是个程序库,它将Linux的epoll.BSD类操作系统的kqueue等事件处理功能封装成统一的接口.即使对服务器的连接数增加,也能发挥O(1)的性能 ...