在程序中使用多线程是不可避免的,java中的多线程还是相对比较容易使用的,下面简单介绍一下java中多线程的使用。
首先,需要将我们要执行的任务实现Runnable接口并编写run()方法;其次,使用Thread类或者Executor类来驱动执行自定义的任务。这里不再写具体的程序进行详解。
执行线程时,我们推荐使用Executor类,因为相比Thread类有以下优势:
- Executor可以创建不同类型的ExecutorService,例如CachedThreadPool,FixedThreadPool,SingleThreadExecutor等,通过使用FixedThreadPool可以设定产生线程的数目,从而可以一次性完成代价高昂的线程分配的工作。并且,Executor有一个shutdown()方法,调用完该方法后不再接受新提交的任务,这样可以控制某个服务接受任务的时段;
- 如果要取得某个线程执行的结果,需要该任务实现Callable接口并实现call()方法,而该任务的执行必须使用ExecutorService.submit()方法来调用;
- 一般不能捕获从线程中逃逸的异常,但是通过Executor可以捕获在线程中出现的异常。
Thread.yield()方法是对线程调度器切换到另一个线程的一种建议,记住,只是一种建议,不能保证它会被采纳,所以,yield()方法是不能依赖的。
线程的优先级可以自行设置,但是多人建议不要重设线程的优先级。
后台线程可以通过setDaemon(true)来设置,该方法必须在调用start()方法之前。当程序中所有的非后台线程都结束时,该程序中所有的后台线程也都会终止,也就是说,只要程序中还有非后台线程在运行,后台线程就不会结束。后台线程创建的所有的线程会自动设置为后台线程,在使用后台线程时,如果程序结束,即程序中所有的非后台线程都执行完毕,那么后台线程会马上停止,也就是说后台线程可能在任何一个位置被停止,这样就不能控制后台线程的结束方式,不能完成一些必要的清理工作,所以一般情况下不建议使用后台线程,可以使用非后台的Executor,因为Executor可以控制所有的任务同时关闭。
在测试后台线程时,使用以下代码进行测试,发现当程序结束后,deamon线程还在一直运行,后来经查才发现原来是ExecutorService的问题,ExecutorService在不调用shutdown()方法之前,一直处于运行的状态,在下面的代码中如果对exec调用shutdown()方法则没有任何问题。
public class TestThread {
/**
* @param args */ public static void main(String[] args) { // TODO Auto-generated method stub try{ ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) exec.execute(new LiftOff()); } catch (Exception e) { e.printStackTrace(); } Thread t = new Thread(new DaemonThread()); t.setDaemon(true); t.start(); System.out.println("Waiting for LiftOff"); } public static class DaemonThread implements Runnable {@Override
public void run() { // TODO Auto-generated method stub while (true) { System.out.println("I am deamon thread , i am running"); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } public static class LiftOff implements Runnable { protected int countDown = 10; private static int taskCount = 0; private final int id = taskCount++; public LiftOff() {} public LiftOff(int countDown) { this.countDown = countDown; } public String status() { return "#" + id + "(" + (countDown > 0 ? countDown : "LiftOff!") + ")."; } @Override public void run() { // TODO Auto-generated method stub while (countDown-- > 0) { System.out.print(status()); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Thread.yield(); } System.out.println("lift off is over"); } }}