先来区分一下线程和进程!!!
进程是资源分配的最小单位。
线程是cup调度的最小单位,对于系统开销来说,线程比进程的开销小。
一个程序可以有多个进程,一个进程可以有多个线程。
进程间资源独立,一个进程的多个线程之间共享该进程的资源。
线程不能独立运行必须依赖于进程和应用程序的调用。
进程会由系统分配地址空间,而线程没有独立的地址空间,共享所属进程的地址空间。
线程(英语:thread)是操作系统能够进行运算调度的最小单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程之间并行执行不同的任务。
Java 线程状态分为以下6种:
- NEW 初始状态,线程刚被创建,未调用start()方法。
- RUNNABLE 运行状态,Java中将就绪和运行中都笼统的称作运行中。
- BLOCKED 阻塞状态,表示线程此时阻塞于锁。
- WAITING 等待状态,表示此时线程处于等待状态,等待其他线程做出一些特定动作(通知或者唤醒)。
- TIME_WAITING 超时等待,与WAITING不同的是:可以指定等待时间,超过时间就自行返回。
- TERMINATED 终止状态,表示当前线程已经执行完毕。
Java 线程状态变迁如下图所示(图源《Java 并发编程艺术》4.1.4节)
面试问题:为什么不是调用run( )方法就开始运行?
就像百米赛跑,run()方法只是安排了谁要怎么去跑,而调用了start( )才真正鸣枪开始跑。
- 线程创建之后它将处于 NEW 状态,只有调用
start()
方法后开始运行。- 可运行状态的线程获得了 cpu 时间片(timeslice)后就处于RUNNING(运行) 状态。
- 当线程执行
wait()
方法之后,线程进入 **WAITING(等待)**状态。- 进入等待状态的线程需要依靠其他线程的通知才能够返回到运行状态,而 TIME_WAITING(超时等待) 状态相当于在等待状态的基础上增加了超时限制,比如通过
sleep(long millis)
方法或wait(long millis)
方法可以将 Java 线程置于 TIMED WAITING 状态。当超时时间到达后 Java 线程将会返回到 RUNNABLE 状态。- 当线程调用同步方法时,在没有获取到锁的情况下,线程将会进入到 BLOCKED(阻塞) 状态。
- 线程在执行完
run()
方法之后将会进入到 TERMINATED(终止) 状态。
线程的创建方式:
①继承 Thread 类,并覆写run方法;
private static class MyThread extends Thread{
/*@Override
public void run() {
System.out.println("通过继承创建一个线程");
}
*/
}
//创建并启动
new MyThread().start();
②实现Runable接口
private static class MyRunable implements Runnable {
@Override
public void run() {
System.out.println("实现Runnable接口创建一个线程");
}
}
//创建接口,创建线程,并将接口作为参数
new MyRunable().run;
③通过Callable接口实现
private class MyRunable implements Callable {
private String name;
private MyRunable(String name){
this.name = name;
}
@Override
public String call()throw Exception {
return name;
}
}
FutrueTask task = new FutrueTask(new MyRunable("线程"));
new Thread(task).start();
System.out.println(task.get());
当我们创建线程的时候,若不指定名字,JVM会给定一个名字从Thread-0开始(可以使用JConsole工具来查看线程名称以及其他相关信息)