线程的创建
Java使用Thread类代表线程,所有线程对象都必须是Thread类或其子类,线程创建方式有四种方式:
1、继承Thread类
public class MyThread extends Thread{
@Override
public void run() {
//重写run方法
}
}
public static void main(String[] args){
new MyThread().start();//创建并启动线程
}
2、实现Runnable接口
将线程对象和线程任务对象分开,降低了耦合度,利于维护
public class MyThread implements Runnable{
public void run() {
//重写run()方法
}
}
public static void main(String[] args){
new Thread(new MyThread()).start();//创建并启动线程
}
3、使用Callable和Future
和Runnable接口不一样,Callable接口提供了一个call()方法作为线程执行体,call()方法比run()方法功能要强大。
1)call()方法可以有返回值
2)call()方法可以声明抛出异常
public class MyTread implements Callable<Integer>{
public Integer call() throws Exception {
//代码实现
return 0;
}
}
try {
FutureTask<Integer> task = new FutureTask<Integer>(new MyTread());
Thread thread = new Thread(task);
thread.start();
Integer result = task.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
4、使用线程池如Executor框架
线程的终止
有三种方法可以使线程终止:
1、使用stop方法强行终止线程
使用stop方法可以强制终止正在执行的线程:thread.stop();
这样虽然可以终止线程,但使用stop方法时很危险的,这样的强制终止会产生不可预料的结果,不推荐使用stop方法来终止线程
2、使用退出标志,时线程正常退出,也就是run()方法完成后线程终止
当线程的run()方法执行完后,线程就会退出,比如监听类的线程永远不会结束,这种情况下一般将线程放在一个循环中条件就是退出标志使用boolean类型
public class MyThread extends Thread
{
public volatile boolean exit = false;
public void run()
{
while (!exit){
//代码
}
}
public static void main(String[] args) throws Exception
{
MyThreadthread = new MyThread();
thread.start();
sleep(5000); // 主线程延迟5秒
thread.exit = true; // 终止线程thread
thread.join();
}
}
3、使用interrupt方法中断线程
执行interrupt()方法中断线程,退出run()方法
public class MyTread extends Thread{
@Override
public void run() {
while(!this.isInterrupted()){
try {
//代码
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String argv[])throws InterruptedException{
MyTread thread=new MyTread ();
thread.setName("MyTread ");
thread.start();
Thread.sleep(2000);
thread.interrupt();
}
常用方法
start() :开启线程的方法
sleep():释放CPU使用权,不释放锁
wait():释放CPU使用权,释放锁
yied():对当前线程进行临时暂停
interrupt():中断线程
join():让线程加入执行,执行某一线程时,当前线程会被暂停,等待某一线程执行结束或超时,该线程才会恢复到可执行状态
线程的生命周期
线程是一个动态执行的过程,有一个从产生到死亡的过程,一个线程有五种状态:新建、就绪、运行、死亡、阻塞
1、新建(new)
当线程对象创建后,即进入了新建状态,如: Thread thread = new Thread();
2、就绪(runnable)
当调用线程的start()方法后: thread.start(); 线程进入就绪状态
处于就绪状态说明线程已经做好准备了,随时等待CPU调度执行,并不是执行了thread.start()方法thread线程就会立即执行
3、运行(running)
当CPU开始调度处于就绪状态的线程时,此线程才得以真正执行,即进入运行状态,就绪状态是进入运行状态的唯一入口,只有线程处于就绪状态,才能被CPU调度进入运行状态
4、死亡(dead)
当线程执行完了或因异常退出了run()方法,该线程结束生命周期,即死亡
5、阻塞(blocked)
处于运行中的线程由于某种原因,暂时放弃了对CPU的使用权,停止执行,此时进入阻塞状态直到线程进入就绪状态才有机会再次进入运行状态
阻塞可以分为三种:
1)等待阻塞
运行中的线程执行wait()方法,使线程进入等待阻塞状态
2)同步阻塞
线程在获取synchronized同步锁失败(因为锁被其他线程占用),线程会进入阻塞状态
3)其他阻塞
通过调用线程的sleep()或join()或发出I/O请求是,线程进入阻塞状态,当sleep()状态超时,join()等待线程结束或超时,I/O处理完毕,线程重新进入就绪状态