索引目录
1、线程的状态
2、线程等待和唤醒
3、线程休眠和中断
4、为程序添加退出事件
5、线程组
正文内容
1、线程的状态
线程的6种状态如下图
2、线程等待和唤醒
void wait(): 使线程陷入一直等待的状态,除非被唤醒。
void wait(long timeout): 使线程等待timeout指定的毫秒数。
void wait(long timeout,int nanos): 使线程等待timeout指定的毫秒数+nanos指定的微妙数。
void notify(): 唤醒在此对象上等待的一个对象,如果这个对象上有许多对象同时在等待,则任意唤醒其中一个。
void notifyAll(): 唤醒在此对象上等待的所有对象。
拓展:
(1)、通过继承Thread基类创建子线程。“多实例,多线程”。唤醒这类线程只能采取一一唤醒的策略。
(2)、通过实现Runnable接口创建子线程。可以设置成“单实例、多线程”也可以“多实例,多线程”。
案例1——通过继承Thread“多实例,多线程”
public class NotifyWaitingThread
{
public static void main(String[] args) throws InterruptedException
{
MyThread[] threads=new MyThread[3];
for(int i=0;i<3;i++)
{
threads[i]=new MyThread();
threads[i].no=i;
threads[i].setDaemon(true);
threads[i].start();
}
Thread.sleep(500);
for(int i=0;i<3;i++)
{
synchronized(threads[i])
{
threads[i].notify();
}
}
}
}
class MyThread extends Thread
{
public int no=0;
public void run()
{
System.out.println("第"+this.no+"个线程开始等待5分钟");
try
{
synchronized(this)
{
this.wait(5*60*1000);
}
}
catch(InterruptedException ie)
{
ie.printStackTrace();
}
System.out.println("第"+this.no+"个线程被唤醒");
}
}
运行结果:
E:>java NotifyWaitingThread
第0个线程开始等待5分钟
第2个线程开始等待5分钟
第1个线程开始等待5分钟
第0个线程被唤醒
第2个线程被唤醒
第1个线程被唤醒
E:>
详解
A:使用Thread.sleep()使线程开始休眠指定的时间,以便让各个子进程进入等待状态;
B:synchronized代表同步锁。
C: threads[i].notify();发出notify()的对象必须与被锁定的对象保持一致,否则无效
案例2——实现Runnable接口“多实例,多线程”
public class NotifyWaitingThreadWithRunnable
{
public static void main(String[] args) throws InterruptedException
{
Runner[] runners=new Runner[3];
Thread[] threads=new Thread[3];
for(int i=0;i<3;i++)
{
runners[i]=new Runner(i);
threads[i]=new Thread(runners[i]);
threads[i].setDaemon(true);
threads[i].start();
}
Thread.sleep(500);
for(int i=0;i<3;i++)
{
synchronized(runners[i])
{
runners[i].notify();
}
}
}
}
class Runner implements Runnable
{
private int no=0;
public Runner(int no)
{
this.no=no;
}
public void run()
{
System.out.println("第"+this.no+"个线程开始等待5分钟");
try
{
synchronized(this)
{
this.wait(5*60*1000);
}
}
catch(InterruptedException ie)
{
ie.printStackTrace();
}
System.out.println("第"+this.no+"个线程被唤醒");
}
}
运行结果:
E:>java NotifyWaitingThreadWithRunnable
第0个线程开始等待5分钟
第2个线程开始等待5分钟
第1个线程开始等待5分钟
第2个线程被唤醒
第1个线程被唤醒
第0个线程被唤醒
E:>
这里也说明了唤醒具有随机性。
实例三——实现Runnable接口“单实例,多线程”
public class NotifyWaitingThreadWithSameRunnable
{
public static void main(String[] args) throws InterruptedException
{
SameRunner runner=new SameRunner();
Thread[] threads=new Thread[3];
for(int i=0;i<3;i++)
{
threads[i]=new Thread(runner);
threads[i].setDaemon(true);
threads[i].start();
}
Thread.sleep(500);
synchronized(runner)
{
runner.notifyAll();
}
}
}
class SameRunner implements Runnable
{
public void run()
{
System.out.println("线程开始等待5分钟");
try
{
synchronized(this)
{
this.wait(5*60*1000);
}
}
catch(InterruptedException ie)
{
ie.printStackTrace();
}
System.out.println("线程被唤醒");
}
}
运行结果
E:>java NotifyWaitingThreadWithSameRunnable
线程开始等待5分钟
线程开始等待5分钟
线程开始等待5分钟
线程被唤醒
线程被唤醒
线程被唤醒
E:>
本例3个子线程基于同一个实现Runnable接口的SameRunner对象而创建。这是实现了“单实例,多线程”的案例。
3、线程休眠和中断
线程的休眠和中断不同之处在于处于休眠状态的线程并不释放运行资源,在休眠结束之后,不用被JVM 线程调度器再度选中,而可以直接进入运行状态。结束休眠状态有两种途径:
(1)、体配时间到达后,线程重新进入运行状志;
(2) 处于休眠状志的线程遇上java.lang.InterruptException异常从而被迫停止休眠。
使当前线程进入休眠状态的手段是调用Thread类的seep()方法.
void sleep(long timeout): 是当前线程休眠timeout指定的毫秒数。
void sleep(long timeout,int nanous): 是当前线程休眠timeout指定的毫秒数+nanous指定的微妙数。
void interrupt(): 中断线程的休眠状态。
案例:
public class InterruptSleepingThread
{
public static void main(String[] args) throws InterruptedException
{
WaitingThread thread1=new WaitingThread();
thread1.start();
Thread.sleep(500);
synchronized(thread1)
{
thread1.interrupt();
}
}
}
class WaitingThread extends Thread
{
public void run()
{
System.out.println("线程开始休眠5分钟");
try
{
Thread.sleep(5*60*1000);
}
catch(InterruptedException ie)
{
System.out.println("线程被中断休眠");
}
System.out.println("线程结束休眠");
}
}
运行结果:
E:>java InterruptSleepingThread
线程开始休眠5分钟
线程被中断休眠
线程结束休眠
这个案例演示了线程的休眠和中断,中断某线程的休眠需要放在锁定线程的同步锁中。
4、线程的终止
首先声明stop()方法已被禁用,在未来的jdk中会被弃用,官方说它有安全性问题。其实我们可以利用线程的休眠和中断机制实现终止线程,结合下边案例;
public class StopThread
{
public static void main(String[] args) throws InterruptedException
{
MyThread thread1=new MyThread();
thread1.start();
Thread.sleep(5000);
synchronized(thread1)
{
thread1.interrupt();
}
}
}
class MyThread extends Thread
{
public void run()
{
for(int i=0;i<10000;i++)
{
System.out.println("<"+i+">线程运行中......");
try
{
Thread.sleep(1000);
}
catch(InterruptedException ie)
{
System.out.println("线程被终止");
break;
}
}
}
}
运行结果:
E:>java StopThread
<0>线程运行中……
<1>线程运行中……
<2>线程运行中……
<3>线程运行中……
<4>线程运行中……
线程被终止
子线程Thread1计划循环10000次,但在主线程的中断调用之后退出循环,从而结束整个子线程。
提示:每台电脑的运行速度不一样,运行的结果可能不一致。可能会多循环几次或者少循环几次。大致的结果一直,循环几次之后整个子线程因为遭遇到InterruptedException异常而结束。
(待续。。。。)