1.什么是线程? 它与进程有什么区别? 为什么要使用多线程
1.1、线程是指程序在执行过程中, 能够执行程序代码的一个执行单元。 在 Java 语言中, 线程 有 4 种状态: 运行、 就绪、 挂起和结束。
1.2、进程是指一段正在执行的程序。 而线程有时也 被称为轻量级进程, 它是程序执行的最小单元, 一 个进程可以拥有多个线程, 各个线程之间共享程序 的内存空间 (代码段、 数据段和堆空间) 及一些进 程级的资源 (例如打开的文件), 但是各个线程拥有 自己的栈空间。
1.3、在操作系统级别上, 程序的执行都是以进程为 单位的, 而每个进程中通常都会有多个线程互不影 响地并发执行。 多线程的使用为程序研发带来了巨大的便利:
1) 使用多线程可以减少程序的响应时间。
2) 与进程相比, 线程的创建和切换开销更小。
3) 多 CPU 或多核计算机本身就具有执行多线程的能力, 如果使用单个线程, 将无法重复 利用计算机资源, 造成资源的巨大浪费。
4) 使用多线程能简化程序的结构, 使程序便于理解和维护。
2. 多线程的创建方式
2.1、继承Thread类,重写run()方法
示例:
class MyThread1 extends Thread{
public void run(){
System.out.println("Thread Body");
}
}
2.2、实现Runnable接口,并实现该接口的run()方法 推荐使用
示例:
class MyThread2 implements Runnable{
@Override
public void run() {
System.out.println("Thread Body2");
}
}
3. run()方法与start()方法的区别
系统通过调用线程类的 start( )方法来启动一个线程, 此时该线程处于就绪状态, 而非运行状态, 也就意味着这个线程可以被 JVM 来调度执行。 在调度过程中, JVM 通过调用线程类的 run()方法来完成实际的操作, 当 run()方法结束后,此线程就会终止。
如果直接调用线程类的 run()方法, 这会被当作一个普通的函数调用, 程序中仍然只有主 线程这一个线程, 也就是说, start ()能够异步地调用 run( )方法, 但是直接调用 run( )方法却是同步的, 因此也就无法达到多线程的目的。
由此可知, 只有通过调用线程类的 start( )方法才能真正达到多线程的目的。
代码示例:
/**
* 这里要验证的是run()方法和start()方法的区别
*/
class ThreadDemo implements Runnable{
//静态变量为所有实例所共享
private static int i = 1;
@Override
public void run() {
System.out.println(String.format("ThreadDemo%d:begin",i++));
try{
Thread.sleep(2000);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(String.format("ThreadDemo%d:end",i));
}
}
public class ThreadTest2 {
public static void test1(){
System.out.println("test1:begin");
Thread t1=new Thread(new ThreadDemo());
t1.start();
System.out.println("test1:end");
}
public static void test2(){
System.out.println("test2:begin");
Thread t1=new Thread(new ThreadDemo());
t1.run();
System.out.println("test2:end");
}
public static void main(String[] args) {
/**
* 这里可以将test1() 分别放在try上面和try下面,分别观察结果,可以发现,在test1中的打印语句不需要等待t1.start()完成后就可以运行,
* 也就是说,main线程与t1线程是异步执行的,而从test2可以看出
*/
try {
Thread.sleep(5000);
}catch (InterruptedException e){
e.printStackTrace();
}
test1();
System.out.println();
test2();
}
}
运行结果:运行两次:
从这两次的运行结果可以发现,程序的运行顺序是:
mian() -->主线程阻塞5秒
test1()-->t1线程和主线程异步执行,从test1:begin test1:end 的
结果可以看出(从侧面指出这部分也是主线程的内容) 且t1进入阻塞状态
换行
test2()-->test2中的内容依然是主线程中的,在调用sleep后主线程进入阻塞状态,
此时t1线程接替执行,t1随后调用sleep进入阻塞状态,主线程接替,
当主线程进行完成后,t1继续执行