1.什么是进程?
可以理解为一个程序,比如qq、微信。
2.什么是线程?
线程是进程中的实际运行单位,是操作系统进行运算调度的最小单位。可理解为线程是进程中的一个最小运行单元。在Java语言中,线程有5种状态:新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)。
3.进程和线程的区别?
线程是进程的一部分,进程是一段正在运行的程序,而线程有时也被称为轻量级进程,它是进程的执行单元,一个进程可以拥有多个线程,多个线程可以同时进行,各个线程之间共享程序的内存空间,各个线程拥有自己的栈空间。但是,不同进程使用不同内存空间。
4.为什么使用多线程?
(1)、使用多线程可以减少程序的响应时间。单线程如果遇到等待或阻塞,将会导致程序不响应鼠标键盘等操作,使用多线程可以解决此问题,增强程序的交互性。
(2)、与进程相比,线程的创建和切换开销更小,因为线程共享代码段、数据段等内存空间。
(3)、多核CPU,多核计算机本身就具有执行多线程的能力,如果使用单个线程,将无法重复利用计算资源,造成资源的巨大浪费。
(4)、多线程可以简化程序的结构,使程序便于维护,一个非常复杂的进程可以分为多个线程执行。
(5)、为了更好的利用cpu的资源,如果只有一个线程,则第二个任务必须等到第一个任务结束后才能进行,如果使用多线程则在主线程执行任务的同时可以执行其他任务,而不需要等待;
为了解决负载均衡问题,充分利用CPU资源.为了提高CPU的使用率,采用多线程的方式去同时完成几件事情而不互相干扰.为了处理大量的IO操作时或处理的情况需要花费大量的时间等等,比如:读写文件,视频图像的采集,处理,显示,保存等
5,多线程的缺点?
(1).如果有大量的线程,会影响性能,因为操作系统需要在它们之间切换.
(2).更多的线程需要更多的内存空间
(3).线程中止需要考虑对程序运行的影响.
(4).通常块模型数据是在多个线程间共享的,需要防止线程死锁情况的发生
6.什么时候会用到线程?
答案:当系统中或者开发中。遇到高并发并行的情况下为了解决负载均衡的问题,就会使用到线程。线程可以提高cpu的利用率。 在一个时间点上。Cpu只能支持一个线程的运行(由于windows在一个进程中将多个线程执行速度非常的快。所以好多人认为是那是多线程。其实在同一个时间点上只有一个线程在运行)。
注意:真正的多线程就是当你的机器为双cpu或者是双核的。那么这个时候确实是真正的多线程在运行。
7.java中实现线程(共有三种方法):
1)、继承Thread类:
步骤:①、定义类继承Thread;
②、复写Thread类中的run方法;
目的:将自定义代码存储在run方法,让线程运行
③、调用线程的start方法:
该方法有两步:启动线程,调用run方法。
2)、实现Runnable接口: 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为run 的无参方法。
步骤: ①、定义类实现Runnable接口
②、覆盖Runnable接口中的run方法
将线程要运行的代码放在该run方法中。
③、通过Thread类建立线程对象。
④、将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程执行指定对象的run方法就要先明确run方法所属对象
⑤、调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。
3)、通过Callable和Future创建线程
继承Thread类和实现Runnable接口、实现Callable接口的区别:
继承Thread:线程代码存放在Thread子类run方法中。
优势:编写简单,可直接用this.getname()获取当前线程,不必使用Thread.currentThread()方法。
劣势:已经继承了Thread类,无法再继承其他类。
实现Runnable:线程代码存放在接口的子类的run方法中。
优势:避免了单继承的局限性、多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形。
劣势:比较复杂、访问线程必须使用Thread.currentThread()方法、无返回值。
实现Callable:
优势:有返回值、避免了单继承的局限性、多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形。
劣势:比较复杂、访问线程必须使用Thread.currentThread()方法。
线程的生命周期:
新建 :从新建一个线程对象到程序start() 这个线程之间的状态,都是新建状态;
就绪 :线程对象调用start()方法后,就处于就绪状态,Java虚拟机会为其创建方法调用栈和程序计数器,等待调度运行;
运行 :就绪状态下的线程在获取CPU资源后就可以执行run(),此时的线程便处于运行状态,运行状态的线程可变为就绪、阻塞及 死亡三种状态。
阻塞 :当处于运行状态的线程失去所占用资源之后,便进入阻塞状态;
死亡:线程在run()方法执行结束后进入死亡状态。此外,如果线程执行了interrupt()或stop()方法,那么它也会以异常退出的方式进入死亡状态。
线程状态之间的转换:
线程同步:
多个线程同时访问同一资源时。线程与线程之间协调的这一过程就叫做线程同步。
A)synchronized()方法,指同步方法的意思。锁定线程。同步方法实际就是在执行方法的时候当前的对象被锁定。(锁定方法实际就是锁定了当前方法的对象。必须等当前线程执行完才能执行下一个线程),线程的同步也就是使线程处于安全化状态。
B)线程的死锁:两个线程相互等待的状态就形成了死锁。
C)如何解决死锁:加大锁的粒度
为什么要进行线程同步?
java允许多线程并发控制,当多个线程同时操作一个可共享资源变量时(如对其进行增删改查操作),会导致数据不准确,而且相互之间产生冲突。所以加入同步锁以避免该线程在没有完成操作前被其他线程调用,从而保证该变量的唯一性和准确性。
同步的前提:
1、必须要有两个或者两个以上的线程。
2、必须是多个线程使用同一个锁。
3、必须保证同步中只能有一个线程在运行。
4、只能同步方法,不能同步变量和类。
5、不必同步类中所有方法,类可以拥有同步和非同步的方法。
6、如果一个线程在对象上获得一个锁,就没有任何其他线程可以进入(该对象的)类中的任何一个同步方法。
7、线程睡眠时,它所持的任何锁都不会释放。
好处:解决了多线程的安全问题。
弊端:多个线程需要判断,消耗资源,降低效率。
死锁
进程A中包含资源A,进程B中包含资源B,A的下一步需要资源B,B的下一步需要资源A,所以它们就互相等待对方占有的资源释放,所以也就产生了一个循环等待死锁。
死锁形成的必要条件总结(都满足之后就会产生):
①、互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源;
②、请求与保持条件:进程获得一定的资源之后,又对其他资源发出请求,但是该资源可能被其他进程占有,此事请求阻塞,但又对自己获得的资源保持不放;
③、不可剥夺条件:是指进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用完后自己释放
④、循环等待条件:系统中若干进程形成环路,该环路中每个进程都在等待相邻进程占用的资源。