续上篇博客,接着从线程的终止这个话题开始。
1、线程的终止
前边提倡的使用线程的休眠和中断机制实现线程的终止,很完美,但其实JDK中还可以使用Thread.join()方法来实现线程的终止。注意的是这个join方法不能真正的终止一个线程,而是提供一个堵塞当前线程,等待某个线程终止的途径。
void join():一直堵塞当前线程,等待线程结束。遇到中断会抛出InteruptedException异常。
void join(long timeout): 指定的毫秒时间内堵塞当前线程,等待线程结束。遇到中断会抛出InteruptedException异常。
void join(long timeout ,int nanous): 指定的毫秒+nanous指定的微妙时间内堵塞当前线程,等待线程结束。遇到中断会抛出InteruptedException异常。
案例如下:
public class JoinThread
{
public static void main(String[] args) throws InterruptedException
{
TestThread thread1=new TestThread();
thread1.start();
long beginTime=System.currentTimeMillis();
thread1.join();
long endTime=System.currentTimeMillis();
System.out.println("等待"+(endTime-beginTime)/1000+"秒后线程终止");
}
}
class TestThread extends Thread
{
public void run()
{
for(int i=0;i<10;i++)
{
System.out.println("<"+i+">线程运行中......");
try
{
Thread.sleep(1000);
}
catch(InterruptedException ie)
{
ie.printStackTrace();
}
}
}
}
运行结果:
E:>java JoinThread
<0>线程运行中……
<1>线程运行中……
<2>线程运行中……
<3>线程运行中……
<4>线程运行中……
<5>线程运行中……
<6>线程运行中……
<7>线程运行中……
<8>线程运行中……
<9>线程运行中……
等待10秒后线程终止
运行结果演示的是主线程等待子线程Thread1结束,并打印耗费在等待上面的时间。
当然啦,如果子线程运行时间较长,同时又不愿意主线程无线阻塞一直等待子线程结束的话可以下边的代码实例,间歇性等待一段时间之后,如果任然没有结束,则转而处理其他任务。
//循环标志
thread.join(一段时间);
if(thread.isAlive())//如果线程任然没有结束
{
//处理其他任务
continue;//循环标志
}
除此之外,还有yield()方法,可以使线程主动让出CPU时间片,回到就绪状态,等待JVM线程调度器再次选中该线程。
案例代码如下:
public class YieldThread
{
public static void main(String[] args) throws InterruptedException
{
SleepingThread thread1=new SleepingThread(1);
SleepingThread thread2=new SleepingThread(2);
thread1.start();
thread2.start();
Thread.sleep(5000);
thread1.yield();
if(thread1.isAlive())
System.out.println("线程1仍然存活");
}
}
class SleepingThread extends Thread
{
private int no=0;
public SleepingThread(int no)
{
this.no=no;
}
public void run()
{
for(int i=0;i<10;i++)
{
System.out.println("<"+i+">"+this.no+"线程运行中......");
try
{
Thread.sleep(1000);
}
catch(InterruptedException ie)
{
ie.printStackTrace();
}
}
}
}
运行结果如下:
主线程创建并启动两个子线程thread1和thread2.在两个线程的运行中,调用yield()方法使其让出CPU时间片。所以yield方法并不是用于终止线程而是使线程回到就绪状态。
2、为程序添加退出事件
java.lang.Runtime类提供了一个addShutdownHook(Thread hook)方法,添加虚拟机关闭钩子。首先说明虚拟机关闭钩子的作用以下两点
(1)应用程序正常退出。在退出时执行特定的业务逻辑。
(2)虚拟机非正常退出,如用户按下“ctrl+C”组合键,操作系统关闭。在退出时执行必要的挽救措施。
实现方式——将退出事件响应代码放置在一个自定义线程的线程体中。
下边将用代码来实现一个案例——演示如何添加虚拟机关闭钩子。具体描述如下:应用程序如果正常退出,将会打印“应用程序耗时…毫秒”字样;无论应用程序是否正常退出,虚拟机关闭钩子都将控制台上打印“引用程序退出事件被响应”字样。
public class TestOnExit
{
public TestOnExit()
{
doShutDownWork();
}
private void doShutDownWork()
{
Runtime.getRuntime().addShutdownHook(new Thread()
{
public void run()
{
System.out.println("应用程序退出事件被响应");
}
});
}
public static void main(String[] args) throws InterruptedException
{
TestOnExit testor = new TestOnExit();
long beginTime = System.currentTimeMillis();
for (int i = 0; i < 10; i++)
{
Thread.sleep(1000);
}
long endTime = System.currentTimeMillis();
System.out.println("应用程序耗时"+(endTime-beginTime)+"毫秒");
}
}
运行结果:
(1)正常退出
E:>java TestOnExit
应用程序耗时10001毫秒
应用程序退出事件被响应
(2)使用组合键“Ctrl+C”非正常退出
E:>java TestOnExit
应用程序退出事件被响应