您的位置:首页 > 编程语言 > Java开发

Java基本线程机制(四)

2013-12-17 16:21 302 查看
八、后台线程

后台线程,指在程序运行的时候再后台提供一种通用服务的线程,这种线程并不是程序不可或缺的部分。因此,当程序中所有的非后台线程都结束时,程序也就终止了,同时会杀死进程中的所有后台进程。

public class SimpleDeamons implements Runnable {

@Override
public void run() {
try {
while(true){
TimeUnit.MILLISECONDS.sleep(100);
System.out.println(Thread.currentThread() + " " + this);
}
} catch (InterruptedException e) {
System.out.print("sleep interrupt");
}
}

public static void main(String[] args)throws Exception {
for(int i = 0; i < 10; i++){
Thread deamon = new Thread(new SimpleDeamons());
deamon.setDaemon(true);
deamon.start();
}
System.out.print("All deamon started");
TimeUnit.MILLISECONDS.sleep(175);
}

}

必须在Thread.start()之前设置setDaemon(true);否则无效。
可以设计一个专门产生后台线程的线程工厂

public class DaemonThreadFactory implements ThreadFactory {

@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}

}

可以将这个线程工厂的对象传给Executors中生产ExecutorService的三个方法。则这个线程池中的所有线程都是后台线程
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class DaemonFromFactory implements Runnable {

@Override
public void run() {
try {
while(true){
TimeUnit.MILLISECONDS.sleep(100);
System.out.println(Thread.currentThread() + " " + this);
}
} catch (InterruptedException e) {
System.out.print("sleep interrupt");
}
}

public static void main(String[] args)throws Exception {
ExecutorService exe = Executors.newCachedThreadPool(new DaemonThreadFactory());
for(int i = 0; i < 10; i++){
exe.execute(new DaemonFromFactory());
}
System.out.print("All deamon started");
TimeUnit.MILLISECONDS.sleep(500);
}

}

ThreadFactory可以自定义创建一些具有默认属性的线程。可以通过isDaemon()方法确定一个线程是否是一个后台线程。
所有由后台线程生成的子线程都默认是后台线程。

以下的finally字句将不会执行,即后台线程不一定会被执行完毕。

import java.util.concurrent.TimeUnit;

public class ADaemon implements Runnable {

@Override
public void run() {
try {
System.out.println("ADaemon start");
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
System.out.println("this statement will not done.");
}
}

public static void main(String[] args) {
Thread t = new Thread(new ADaemon());
t.setDaemon(true);
t.start();
}

}


九、创建对象的时候启动线程
public class SelfManage implements Runnable {
private int countDown = 5;
private Thread t = new Thread(this);
public SelfManage(){
t.start();
}
@Override
public void run() {
while(countDown-- >= 0){
System.out.println(this);
}
}
public String toString(){
return Thread.currentThread().getName() + "(" + countDown + ")";
}
public static void main(String[] args) {
for(int i = 0; i < 5; i++){
new SelfManage();
}
}

}


十、加入一个线程
可以在一个线程中加入另一个线程,调用Thread.join()方法,则此时该线程会被挂起,知道被加入的线程执行完毕才会被唤醒。也可以在掉用join()方法时带一个超市参数,如果被加入的线程在这段时间内未执行完,则此方法也会返回,让后执行该线程。

class Sleeper extends Thread{
private int duration;
public Sleeper(String name, int sleepTime){
super(name);
this.duration = sleepTime;
start();
}
public void run(){
try {
sleep(duration);
} catch (InterruptedException e) {
System.out.println(getName() + " was interrupt." + "isInterrupted():" + isInterrupted());
return;
}
System.out.println(getName() + " is awakened");
}
}

class Joiner extends Thread{
private Sleeper sleeper;
public Joiner(String name, Sleeper sleeper){
super(name);
this.sleeper = sleeper;
start();
}
public void run(){
try {
sleeper.join();
} catch (InterruptedException e) {
System.out.println("Interrupted");
return;
}
System.out.println(getName() + "Join completed");
}
}

public class Joining {
public static void main(String[] args) {
Sleeper sleepy = new Sleeper("sleepy", 500),
grumpy = new Sleeper("grumpy", 500);
Joiner dopey = new Joiner("dopey", sleepy),
doc = new Joiner("Doc", grumpy);
grumpy.interrupt();
}

}


十一、捕获异常
如果在子线程中抛出一个异常,则在主线程中是捕获不到的。如:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExceptionThread implements Runnable {

@Override
public void run() {
throw new RuntimeException();
}
public static void main(String[] args){
ExecutorService exe = Executors.newCachedThreadPool();
try{
exe.execute(new ExceptionThread());
}catch(Exception e){
System.out.println("caught exception");
}
}

}

为解决这个问题,我们可以改变Executor产生线程的方法,将一个线程工厂传给Executor的创建线程池的方法,这个工厂会为每一个他所创建的线程添加一个异常处理器。
Thread.UncaughtExceptionHandler是Java SE5的一个新接口,他里面的方法uncaughtException()会捕获线程中抛出的异常。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

class ExceptionThread2 implements Runnable{
public void run(){
Thread t = Thread.currentThread();
System.out.println("run() by " + t);
System.out.println("en:" + t.getUncaughtExceptionHandler());
throw new RuntimeException();
}
}

class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{

@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("catch " + e);
}

}

class HandlerThreadFactory implements ThreadFactory{

@Override
public Thread newThread(Runnable r) {
System.out.println(this + " create new thread");
Thread t = new Thread(r);
System.out.println("create " + t);
t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
System.out.println("eh:" + t.getUncaughtExceptionHandler());
return t;
}

}

public class CaptureUncaughtException {
public static void main(String[] args) {
ExecutorService exe = Executors.newCachedThreadPool(new HandlerThreadFactory());
exe.execute(new ExceptionThread2());
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息