简述线程,程序、进程的基本概念。以及他们之间关系是什么?
1. 简述线程,程序、进程的基本概念。以及他们之间关系是什么?
线程与进程相似,但线程是⼀个⽐进程更⼩的执⾏单位。⼀个进程在其执⾏的过程中可以产⽣多个线程。与进程不同的是同类的多个线程共享同⼀块内存空间和⼀组系统资源,所以系统在产⽣⼀个线程,或是在各个线程之间作切换⼯作时,负担要⽐进程⼩得多,也正因为如此,线程也被称为轻量级进程。
程序是含有指令和数据的⽂件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码。
进程是程序的⼀次执⾏过程,是系统运⾏程序的基本单位,因此进程是动态的。系统运⾏⼀个程序即是⼀个进程从创建,运⾏到消亡的过程。简单来说,⼀个进程就是⼀个执⾏中的程序,它在计算机中⼀个指令接着⼀个指令地执⾏着,同时,每个进程还占有某些系统资源如CPU时间,内存空间,⽂件,⽂件,输⼊输出设备的使⽤权等等。换句话说,当程序在执⾏时,将会被操作系统载⼊内存中。
线程是进程划分成的更⼩的运⾏单位。线程和进程最⼤的不同在于基本上各进程是独⽴的,⽽各线程则不⼀定,因为同⼀进程中的线程极有可能会相互影响。从另⼀⾓度来说,进程属于操作系统的范畴,主要是同⼀段时间内,可以同时执⾏⼀个以上的程序,⽽线程则是在同⼀程序内⼏乎同时执⾏⼀个以上的程序段。
线程上下⽂的切换⽐进程上下⽂切换要快很多
进程切换时,涉及到当前进程的CPU环境的保存和新被调度运⾏进程的CPU环境的设置。
线程切换仅需要保存和设置少量的寄存器内容,不涉及存储管理⽅⾯的操作。
2. 线程有哪些基本状态?这些状态是如何定义的?
1. 新建(new):新创建了⼀个线程对象。
2. 可运⾏(runnable):线程对象创建后,其他线程(⽐如main线程)调⽤了该对象的start()⽅法。该状态的线程位于可运⾏线程池中,等待
被线程调度选中,获取cpu的使⽤权。
3. 运⾏(running):可运⾏状态(runnable)的线程获得了cpu时间⽚(timeslice),执⾏程序代码。
4. 阻塞(block):阻塞状态是指线程因为某种原因放弃了cpu使⽤权,也即让出了cpu timeslice,暂时停⽌运⾏。直到线程进⼊可运⾏
(runnable)状态,才有机会再次获得cpu timeslice转到运⾏(running)状态。阻塞的情况分三种:
(⼀). 等待阻塞:运⾏(running)的线程执⾏o.wait()⽅法,JVM会把该线程放⼊等待队列(waiting queue)中。
(⼆). 同步阻塞:运⾏(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占⽤,则JVM会把该线程放⼊锁池(lock
pool)中。
(三). 其他阻塞: 运⾏(running)的线程执⾏Thread.sleep(long ms)或t.join()⽅法,或者发出了I/O请求时,JVM会把该线程置为阻塞
状态。当sleep()状态超时join()等待线程终⽌或者超时、或者I/O处理完毕时,线程重新转⼊可运⾏(runnable)状态。
5.死亡(dead):线程run()、main()⽅法执⾏结束,或者因异常退出了run()                      ⽅法,则该线程结束⽣命周期。死亡的线程不可再次复⽣。
备注:可以⽤早起坐地铁来⽐喻这个过程(下⾯参考⾃⽜客⽹某位同学的回答):
1. 还没起床:sleeping
2. 起床收拾好了,随时可以坐地铁出发:Runnable
3. 等地铁来:Waiting
4. 地铁来了,但要排队上地铁:I/O阻塞
5. 上了地铁,发现暂时没座位:synchronized阻塞
6. 地铁上到座位:Running
7. 到达⽬的地:Dead
3. 何为多线程?
多线程就是多个线程同时运⾏或交替运⾏。单核CPU的话是顺序执⾏,也就是交替运⾏。多核CPU的话,因为每个CPU有⾃⼰的运算器,所以在多个CPU中可以同时运⾏。
4. 为什么多线程是必要的?
1. 使⽤线程可以把占据长时间的程序中的任务放到后台去处理。
2. ⽤户界⾯可以更加吸引⼈,这样⽐如⽤户点击了⼀个按钮去触发某些事件的处理,可以弹出⼀个进度条来显⽰处理的进度。
3. 程序的运⾏速度可能加快。
5 使⽤多线程常见的三种⽅式
①继承Thread类
MyThread.java
public class MyThread extends Thread {
@Override
public void run() {
super.run();
System.out.println("MyThread");
}
}
Run.java
public class Run {
public static void main(String[] args) {
MyThread mythread = new MyThread();
mythread.start();
System.out.println("运⾏结束");
}
}
运⾏结果:从上⾯的运⾏结果可以看出:线程是⼀个⼦任务,CPU以不确定的⽅式,或者说是以随机的时间来调⽤线程中的run⽅法。
③使⽤线程池
在《阿⾥巴巴Java开发⼿册》“并发处理”这⼀章节,明确指出线程资源必须通过线程池提供,不允许在应⽤中⾃⾏显⽰创建线程。
为什么呢?
使⽤线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源开销,解决资源不⾜的问题。如果不使⽤线程池,有可能会造成系统创建⼤量同类线程⽽导致消耗完内存或者“过度切换”的问题。
另外《阿⾥巴巴Java开发⼿册》中强制线程池不允许使⽤ Executors 去创建,⽽是通过 ThreadPoolExecutor 的⽅式,这样的处理⽅式让写的同学更加明确线程池的运⾏规则,规避资源耗尽的风险
Executors 返回线程池对象的弊端如下:
FixedThreadPool 和 SingleThreadExecutor :允许请求的队列长度为 Integer.MAX_VALUE,可能堆积⼤量的请求,从⽽导致OOM。
CachedThreadPool 和 ScheduledThreadPool :允许创建的线程数量为 Integer.MAX_VALUE ,可能会创建⼤量线程,从⽽导致OOM。
6 线程的优先级
每个线程都具有各⾃的优先级,线程的优先级可以在程序中表明该线程的重要性,如果有很多线程处于就绪状态,系统会根据优先级来决定⾸先使哪个线程进⼊运⾏状态。但这个并不意味着低优先级的线程得不到运⾏,⽽只是它运⾏的⼏率⽐较⼩,如垃圾回收机制线程的优先级就⽐较低。所以很多垃圾得不到及时的回收处理。
线程优先级具有继承特性。⽐如A线程启动B线程,则B线程的优先级和A是⼀样的。
线程优先级具有随机性。也就是说线程优先级⾼的不⼀定每⼀次都先执⾏完。
Thread类中包含的成员变量代表了线程的某些优先级。如Thread.MIN_PRIORITY(常数1),Thread.NORM_PRIORITY(常数进程间通信和线程间通信的区别
5), Thread.MAX_PRIORITY(常数10)。其中每个线程的优先级都在Thread.MIN_PRIORITY(常数1)到Thread.MAX_PRIORITY(常数10)之间,在默认情况下优先级都是Thread.NORM_PRIORITY(常数5)。
学过操作系统这门课程的话,我们可以发现多线程优先级或多或少借鉴了操作系统对进程的管理。
7 Java多线程分类
⽤户线程
运⾏在前台,执⾏具体的任务,如程序的主线程、连接⽹络的⼦线程等都是⽤户线程
守护线程
运⾏在后台,为其他前台线程服务.也可以说守护线程是JVM中⾮守护线程的 “佣⼈”。
特点:⼀旦所有⽤户线程都结束运⾏,守护线程会随JVM⼀起结束⼯作
应⽤:数据库连接池中的检测线程,JVM虚拟机启动后的检测线程
最常见的守护线程:垃圾回收线程
如何设置守护线程?
可以通过调⽤ Thead 类的 setDaemon(true) ⽅法设置当前的线程为守护线程。
注意事项:
1. setDaemon(true)必须在start()⽅法前执⾏,否则会抛出IllegalThreadStateException异常
2. 在守护线程中产⽣的新线程也是守护线程
3. 不是所有的任务都可以分配给守护线程来执⾏,⽐如读写操作或者计算逻辑
8 sleep()⽅法和wait()⽅法简单对⽐
两者最主要的区别在于:sleep⽅法没有释放锁,⽽wait⽅法释放了锁。
两者都可以暂停线程的执⾏。
Wait通常被⽤于线程间交互/通信,sleep通常被⽤于暂停执⾏。
wait()⽅法被调⽤后,线程不会⾃动苏醒,需要别的线程调⽤同⼀个对象上的notify()或者notifyAll()⽅法。sleep()⽅法执⾏完成后,线程会⾃动苏醒。
9 为什么我们调⽤start()⽅法时会执⾏run()⽅法,为什么我们不能直接调⽤run()⽅法?
这是另⼀个⾮常经典的java多线程⾯试问题,⽽且在⾯试中会经常被问到。很简单,但是很多⼈都会答不上来!
new⼀个Thread,线程进⼊了新建状态;调⽤start()⽅法,会启动⼀个线程并使线程进⼊了就绪状态,当分配到时间⽚后就可以开始运⾏了。start()会执⾏线程的相应准备⼯作,然后⾃动执⾏run()⽅法的内
容,这是真正的多线程⼯作。⽽直接执⾏run()⽅法,会把run⽅法当成⼀个mian线程下的普通⽅法去执⾏,并不会在某个线程中执⾏它,所以这并不是多线程⼯作。
总结:调⽤start⽅法⽅可启动线程并使线程进⼊就绪状态,⽽run⽅法只是thread的⼀个普通⽅法调⽤,还是在主线程⾥执⾏。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。