JAVA-线程知识点汇总

线程是程序执行的最小单元,进程是程序执行的一个代码块,是系统进行资源分配和调度的一个独立单位,一个进程可以包含多个线程。
多线程的使用为程序研发提供了便利,具体内容如下:
1)使用多线程可以缩短程序的响应时间,使用多线程,可以把耗时的线程分配到一个单独的线程去执行,从而使程序具备了良好的交互性;
2)与进程相比,线程的创建和切换开销小,线程在数据共享方面效率非常高;
3)多cpu和多核计算器本身就具有处理多线程的能力,如果使用单个线程,无法重复利用计算机资源;
4)使用多线程能简化程序的结构,使程序便于理解和维护。

多线程的实现有三种方法:
1,继承Thread类,重写run()方法;(extends Thread)
Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,启动线程的唯一方法就是通过Thread类的start()方法。start()是一个本地方法,它将启动一个新线程,并执行run()方法;不过,调用start()方法并不能直接执行多线程代码,而是使该线程处于可运行态,什么时候执行多线程代码是有操作系统决定的。
2,实现runnable接口,并实现该接口的run()方法:
    1)定义并实现Runnable接口,实现run()方法。
    2)创建Thread类,并用runnable()接口的对象作为参数实例化该Thread对象。
    3)调用Thread的run()方法;

class MyThread implements Runnable{                 //1)
      public void run(){
             System.out.println("Thread body");
       }
}
public class Test{
       public static void main(String[] args){
            MyThreas thread = new MyThread();
            Thread t = new Thread(thread);               //2)
            t.run();                                  //3)
        }
}

3,实现Callable()接口,并重写call()方法
Callable接口实际是Executor框架中的功能类,Callable接口与Runnable接口的功能类似,但是比Runable接口的功能更强大,
    1)Callable可以在任务结束后提供一个返回值,Runable无法提供这个返回值;
    2)call()方法可以抛异常,run()方法不行;
    3)运行Callable可以拿到future对象,Future是异步计算的结果,它提供了检查计算是否完成的方法。由于线程属于异步计算模型,无法从别的线程得到函数的返回值,在这种情况下,就可以使用Future来监视目标线程调用call()方法的情况,当调用Future的get()方法以获取结果时,当前线程就会阻塞,直到call()方法返回结果。
一般使用实现Runnable接口来实现多线程。原因是实现Runnable接口比继承Thread类具有一下优势:
    1):适合多个相同的程序代码的线程去处理同一个资源
    2):可以避免java中的单继承的限制
    3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
    4):线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类

关于start()方法与run()方法:
start()可以启动线程,使线程处于就绪状态,在调度过程中,jvm通过调用线程的run()方法来完成相关的操作,当run()方法结束,线程终止,即start()方法可以异步调用run()方法,而直接调用run()方法时,函数体会被当成一个普通的函数处理,无法达到多线程的目的。
而join()方法,其作用是让调用该方法的线程在执行完run()方法后,继续执行join()方法后的代码。即将两个线程合并,实现同步。

守护线程与用户线程:
守护线程又称“服务线程”,“精灵线程”或者“后台线程”,是指在程序运行时在后台提供一种通用服务的线程,这种线程并不属于程序中不可或缺的部分,而用户线程具有守护线程较高一些的优先级,唯一的不同即当用户线程全部退出执行,只剩下守护线程,那JVM也就退出了。当所有非守护线程运行结束,会同时杀死守护线程,将用户线程设置为守护线程的方法就是在调用start()方法启动线程之前调用对象的setDeamom(true)方法,true为守护线程,false为用户线程。

多线程同步的方法:
1)synchronized关键字(synchronized方法和synchronized块),还可用于静态方法,类或者某个实例
2)wait()方法和notify()方法
     在synchronized代码被执行期间,线程可以调用对象的wait()方法,释放对象锁,进入等待状态,并且可以调用notify()方法或者notifyAll()方法通知正在等待的其他线程,notify()唤醒一个线程,notify()唤醒所有,并让他们竞争。
3)Lock

其中,synchronized与Lock的区别

类别
synchronized
Lock
存在层次
Java的关键字,在jvm层面上
是一个类,需显示的指定起始位置和终止位置,通过代码实现
锁的释放
1、以获取锁的线程执行完同步代码,释放锁 2、线程执行发生异常,jvm会让线程释放锁
在finally中必须释放锁,不然容易造成线程死锁
锁的获取
假设A线程获得锁,B线程等待。如果A线程阻塞,B线程会一直等待
分情况而定,Lock有多个锁获取的方式,具体下面会说道,大致就是可以尝试获得锁,线程可以不用一直等待
锁状态
无法判断
可以判断
锁类型
可重入 不可中断 非公平
可重入 可判断 可公平(两者皆可)
性能
少量同步
大量同步


sleep()和wait()方法:

类别
sleep
wait
原理不同
Thread类的静态方法,是线程用来控制自身流程的,等时间一到,线程自动苏醒
Object类的方法,用于线程间的通信,使当前拥有该对象所的进程等待,知道其他线程调用notify()方法,也可指定时间,
锁的封锁机制
不涉及线程间的通信,调用时不会释放锁,
调用wait()方法后,线程会自动释放掉他所占用的锁,从而使线程所在对象中的其他synchronized数据可被其他线程使用
使用区域不同
sleep()可在任何地方
必须放在同步方法或者同步块中

猜你喜欢

转载自blog.csdn.net/u013363120/article/details/80398725