Java多线程
一.多线程的声明周期
状态名称 | 说明 |
---|---|
New | 初始状态,线程被构建,但是还没有调用start()方法 |
RUNNABLE | 运行状态,Java线程将操作系统中处于就绪和运行两种状态“笼统”地称作“运行中” |
BLOCKED | 阻塞状态,表示线程阻塞于锁 |
WAITING | 等待状态,表示线程进入等待状态,进入该状态表示当前线程需要等待其他线程做出一些特定的动作(通知或中断) |
TIME_WAITING | 超时等待状态,该状态不同于WAITING,它是可以在指定的时间自行返回的 |
TERMINATED | 终止状态,表示当前线程已经执行完毕 |
二.使用线程
有三种使用线程的方法:
- 实现Runnable接口;
- 实现Callable接口;
- 继承Thread方法;
实现Runnable接口
需要实现run方法。通过Thread调用start()方法来启动线程。
public class MyRunnable implements Runnable{
public void run(){
//...
}
}
public static main(String[] args){
MyRunnable instance = new MyRunnable();
Thread thread = new Thread(instance);
thread.start();
}
实现Callable接口
需要实现call()方法,与Runnable相比,Callable可以有返回值,通过call()方法返回,返回值通过FutureTask进行封装。
public class MyCallable implements Callable<Integer> {
public Integer call() {
return 123;
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyCallable myCallable = new MyCallable();
FutureTask ft = new FutureTask(myCallable);
Thread thread = new Thread(ft);
thread.start();
System.out.println(ft.get());
}
继承Thread类
同样也需要实现run()方法,因为Thread类也实现了Runnable接口。
当调用start()方法启动一个线程时,虚拟机会将该线程放入就绪队列中等待调度,当一个线程被调度时会执行该线程的run()方法。
public class MyThread extends Thread{
public void run(){
//...
}
}
public static void main(String[] args){
MyThread myThread = new MyThread();
myThread.start();
}
实现接口和VS继承Thread类,实现接口会更好一点,因为:
- Java不支持多继承,因此继承了Thread类就无法继承其他类,但是可以实现多个接口。
- 类可能只要求可执行就行,继承整个Thread类开销过大。
总结:
实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
4):线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类
提醒一下大家:main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。
三.线程管理
- 如果我们需要让当前正在执行的线程暂停一段时间,并进入阻塞状态,则可以通过调用Thread的sleep方法。sleep()是静态方法,最好不要用Thread的实例对象调用它,因为它睡眠的始终是当前正在运行的线程,而不是调用它的线程对象,它只对正在运行状态的线程对象有效。
public class Test1 {
public static void main(String[] args) throws InterruptedException {
System.out.println(Thread.currentThread().getName());
MyThread myThread=new MyThread();
myThread.start();
myThread.sleep(1000);//这里sleep的就是main线程,而非myThread线程
Thread.sleep(10);
for(int i=0