进程 :是一个正在执行中的程序,每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元;
线程:就是进程中的一个独立控制单元,线程在控制着进程的执行。一个进程中至少有一个进程。
多线程:一个进程中不只有一个线程。
为什么要用多线程?
① 为了更好的利用cpu的资源,如果只有一个线程,则第二个任务必须等到第一个任务结束后才能进行,如果使用多线程则在主线程执行任务的同时可以执行其他任务,而不需要等待;
② 进程之间不能共享数据,线程可以;
③ 系统创建进程需要为该进程重新分配系统资源,创建线程代价比较小;
④ Java语言内置了多线程功能支持,简化了java多线程编程。
线程的状态使用一个枚举类型来描述的。
这个枚举一共有6个值: NEW(新建)、RUNNABLE(运行)、BLOCKED(锁池)、TIMED_WAITING(定时等待)、WAITING(等待)、TERMINATED(终止、结束)。
但是我发现大多数人的理解和上面的这六种还是有些差别,通常会加上阻塞状态,可运行状态,挂起状态。
(1) 继承Thread类
1 2 3 4 5 6 7 8 9 |
|
public class ThreadEx extends Thread {
public void run(){
for (int i = 0; i < 10; i++) {
System.out.println("i = " + i);
}
}
public static void main(String[] args) {
ThreadEx threadEx = new ThreadEx();
threadEx.start();
}
}
//匿名内部类写法
public class ThreadEx {
public static void main(String[] args) {
ThreadEx.MyThread threadEx = new ThreadEx().new MyThread();
threadEx.start();
}
class MyThread extends Thread{
public void run(){
for (int i = 0; i < 10; i++) {
System.out.println("i = " + i);
}
}
}
}
//或
public class ThreadEx {
public static void main(String[] args) {
Thread thread = new Thread(){
public void run(){
for (int i = 0; i < 10; i++) {
System.out.println("i = " + i);
}
}
};
thread.start();
}
}
//合并写法
public class ThreadEx {
public static void main(String[] args) {
new Thread(){
public void run(){
for (int i = 0; i < 10; i++) {
System.out.println("i = " + i);
}
}
}.start();
}
}
(2) 实现Runnable接口
1 2 3 4 5 6 7 8 9 |
|
public class ThreadIm{
public static void main(String[] args) {
ThreadIm.Run run = new ThreadIm().new Run();
Thread t = new Thread(run);
t.start();
}
class Run implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("i = " + i);
}
}
}
}
//改造
public class ThreadIm{
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("i = " + i);
}
}
});
t.start();
}
}
//简化
public class ThreadIm{
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("i = " + i);
}
}
}).start();
}
}
1) start方法:
用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。
2) run():
run()方法只是类的一个普通方法而已,如果直接调用run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待,run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。
总结:调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,还是在主线程里执行。这两个方法应该都比较熟悉,把需要并行处理的代码放在run()方法中,start()方法启动线程将自动调用 run()方法,这是由jvm的内存机制规定的。并且run()方法必须是public访问权限,返回值类型为void。
两种方式的比较 :
实际中往往采用实现Runable接口,一方面因为java只支持单继承,继承了Thread类就无法再继续继承其它类,而且Runable接口只有一个run方法;另一方面通过结果可以看出实现Runable接口才是真正的多线程。
线程是一个动态执行的过程,它有一个从产生到死亡的过程,共五种状态:
新建(new Thread)
当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)
例如:Thread t1=new Thread();
就绪(runnable)
线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t1.start();
运行(running)
线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。
死亡(dead)
当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。
自然终止:正常运行run()方法后终止
异常终止:调用stop()方法让一个线程终止运行
堵塞(blocked)
由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。
正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。
正在等待:调用wait()方法。(调用motify()方法回到就绪状态)
被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)
https://www.cnblogs.com/GooPolaris/p/8079490.html