Java基本线程机制(四)

八、后台线程

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

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());
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值