概述
线程是指程序在执行过程中,能够执行程序代码的一个执行单元。线程也被称为轻量级进程,它是程序执行的最小单元,一个进程可以拥有多个线程,各个线程之间共享程序的内存空间(堆空间、常量池),但是各个线程拥有自己的栈空间。
多线程对于程序的执行有以下几点好处:
- 可以减少程序的响应时间;
- 与进程相比,线程的创建和切换开销更小;
- 能够提高CPU的利用率;
- 能简化程序的结构,使程序便于理解和维护。
线程的生命周期
线程实现方式
1、继承Thread类
主要步骤:
1)自定义MyThread类继承Thread类,重写run()方法;;
2)创建MyThread类的对象;
3)调用run()方法;
pubilc MyThread extends Thread { //继承Thread类
public void run() { //重写run()方法
System.out.println("Thread Body");
}
}
public class Test {
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start(); //开启线程
}
}
2、实现Runnable接口
主要步骤:
1)自定义MyThread类实现Runnable接口,重写run()方法;;
2)用实现Runnable接口的实现类MyThread类的对象作为参数,创建Thread类的对象;
3)调用Thread类的run()方法;
pubilc MyThread implements Runnable { //实现Runnable接口
public void run() { //重写run()方法
System.out.println("Thread Body");
}
}
public class Test {
public static void main(String[] args) {
MyThread mt = new MyThread();
Thread t = new Thread(mt); //创建Thread类的对象
t.start(); //开启线程
}
}
上述两种实现多线程的方式,一般推荐实现Runnable接口的方式。因为一个类在需要被加强或修改时我们才会去继承它,Thread类中有很多方法,只有run()方法是必须要重写的,而Runnable接口中只有一个run()方法。所以从这个角度考虑,实现Runnable接口更好些。
run()方法与start()方法的区别
通常,系统通过调用线程类的start()方法来启动一个线程,此时该线程处于就绪状态,也就意味着这个线程可以被JVM来调度执行。在调度过程中,JVM通过调用线程类的run()方法来完成实际的操作,当run()方法结束后,线程终止。
如果直接调用run()方法,相当于一个普通方法的调用,程序中只有主线程这一个线程。
sleep()方法与wait()方法的区别
1)原理不同。sleep()方法是Thread类的静态方法,是线程用于控制自身流程的。必须指定时间,时间一到,线程自动苏醒。wait()方法是Object的方法,用于线程间的通信。当调用notify()方法(或notifyAll()方法)时,线程苏醒,也可以指定一个时间,时间一到,线程自动苏醒。
2)对锁的处理机制不同。线程调用sleep()方法不会释放锁;线程调用wait()方法时会释放锁。
3)使用区域不同。sleep()法可以放在任何地方使用;而wait()方法必须放在同步方法或同步代码块中使用。
4)抛出异常不同。sleep()方法声明抛出InterruptedException异常;而wait()方法没有声明任何异常。
ps:sleep()方法与yield()方法(线程的礼让方法)的区别
1)sleep()方法结束后,线程的运行不考虑优先级(没有进行线程同步),低优先级的线程也能得到执行权;而yield()方法结束后,只有相同优先级或高优先级的线程能够得到执行权。
2)线程执行sleep()方法后会转入阻塞状态,指定时间内不会被执行;而yield()方法是让当前线程重新回到就绪状态,有可能马上被执行。
3)sleep()方法声明抛出InterruptedException异常;而yield()方法没有声明任何异常。
4)sleep()方法比yield()方法具有更好的移植性。
多线程同步
关于多线程同步,本人懂得比较浅,这里引用一位大神的博客,共同分享、共同学习。
https://blog.csdn.net/wenwen091100304/article/details/48318699
ps:当一个线程执行一个对象的普通synchronized()方法后,其他线程可执行该对象的所有非synchnized()方法和静态synchronized()方法(静态方法用的同步锁是当前类的字节码,非静态方法用的是当前对象)。
symchronized与Lock的区别
1)用法不同。synchronized既可以加在方法上,也可以加在特定代码块中(需指明锁对象)。而Lock需要显示地指定起始位置和终止位置。
2)性能不同。在资源竞争不是很激烈的情况下,synchronized的性能优于Lock接口的实现类ReetrantLock;但是在资源竞争很激烈的情况下,synchronized的性能下降的很快,而ReetrantLock的性能基本保持不变。
3)锁机制不同。synchronized获得锁和释放的方式都是在块结构中,当获取多个锁时,必须以相反的顺序释放锁,并且是自动解锁,不会因为出了异常而导致锁没有被释放引发死锁。而Lock需要开发人员手动去释放锁,并且必须在finally块中释放,否则会引发死锁。此外,Lock的tryLock()方法可以采用非阻塞的方式去获取锁。
参考
https://blog.csdn.net/wenwen091100304/article/details/48318699