Java中多线程技术
最近由于工作的原因开始决定系统学习一下Java的多线程机制。Java语言的一大特点就是内在支持多线程,这和很多语言需要通过外部开发包来实现多线程有本质区别。每个程序都有一个主线程,当程序启动时自动执行。关于多线程的一些概念性东西,见这篇博文:多线程初步。
1、Java内在支持多线程
为什么说Java内在支持多线程呢?根本原因是Java是完全面向对象的,所有Java类都有一个共同的父类-Object类。关于Object类的介绍,可以参考Java官方技术文档,在此提供一个博文链接Object类 。Object类有涉及线程同步的notify()、notifyAll()、wait()、wait(long timeOut)等函数,这些函数可以很好地唤醒或阻塞在当前对象监视器上等待线程。Java中线程有4个状态,创建状态、可运行状态、运行状态、撤消状态。
2、Java多线程的实现
要编写多线程程序,Java中必须直接或间接的使用Thread类或Runnable接口,然后重写run()方法(此方法是完成多线程各自任务的方法)。
2.1Thread类
通过继承Thread类,重写Thread的run()方法,将线程要实现的逻辑放在run()方法中实现。
1)、start方法
start()启动一个线程,当调用start方法后,系统才会开启一个新的线程来执行用户定义的子任务,在这个过程中,会为相应的线程分配需要的资源,不能多次启动一个线程。
2)、run方法
run()方法是不需用户显示调用的,当通过start方法启动一个线程之后,当线程获得了CPU执行时间,便进入run方法体去执行具体的任务。注意,继承Thread类必须重写run方法,在run方法中定义具体要执行的任务。
3)、sleep(long millis) 方法
sleep相当于让线程睡眠,交出CPU,让CPU去执行其他的任务。但要注意,sleep方法不会释放锁,也就是说如果当前线程持有对某个对象的锁,则即使调用sleep方法,其他线程也无法访问这个对象。
4)、yield()方法
调用yield方法会让当前线程交出CPU权限,让CPU去执行其他的线程。它跟sleep方法类似,同样不会释放锁。但是yield不能控制具体的交出CPU的时间,另外,yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会。注意,调用yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,这一点是和sleep方法不一样的。
5)、stop方法
stop方法已经是一个废弃的方法,它是一个不安全的方法。因为调用stop方法会直接终止run方法的调用,并且会抛出一个ThreadDeath错误,如果线程持有某个对象锁的话,会完全释放锁,导致对象状态不一致。所以stop方法基本是不会被用到的。
2.2Runnable接口
有时类本就是属于派生类,但还需实现多线程。由于Java中不支持类的多继承,所以引入Runnable接口,Runnable只有一个未实现的run()方法,然后实例化Thread对象。具体用法参见如下代码: