线程一

1、什么是线程?什么是进程?以及他们之间的关系

       进程:是指一段程序的运行过程,是资源分配的基本单位,

       线程:是CPU独立运行和调度的基本单位,程序执行的最小单位

*两者之间的联系:都是操作系统程序运行的基本单元

*两者的区别:

(1)地址空间:进程之间的地址空间独立,线程共享本进程的地址空间

(2)资源拥有:进城之间资源独立,线程之间共享所属进程的资源,如:内存,CPU,IO等(线程有自己的堆和栈)

(3)执行过程:每个进程都有一个程序执行入口;线程是不能独立执行的,必须依存在进程,由程序的多线程机制控制

(4)健壮性:一个进程奔溃不会影响其他进程的执行,一个线程奔溃会导致进程的奔溃

(5)通信:进程间通信CPI,线程间可以直接读写进程数据段(共享空间)进行通信,但是需要线程的同步和互斥手段,以保证数据一致性

(6)调度和切换:线程上下文切换比进程上下文切换要快很多

2、实现线程的方式?(两种)实现线程的两种方式使用哪一种更好?

(1)继承Thread;(2)实现Runnable接口

实现Runnable接口更好,原因:

(1)java只能是单继承

(2)一个类继承Tread不适合资源共享,相反实现Runnable接口很容易实现资源共享

适合多个相同的程序代码的线程去处理同一个资源 

(3)线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类

不管是扩展Thread类还是实现Runnable接口来实现多线程,最终还是通过Thread的对象的API来控制线程的

3、线程的状态有哪几类,以及状态的转换?

       (1)创建:新建一个线程

       (2)就绪:指调用了线程的start()方法,该状态的线程位于可运行线程池,等待获取CPU的使用权

       (3)运行:就绪的线程获取了CPU,开始执行

       (4)阻塞:线程因为某些原因放弃了CPU,暂时停止工作,只有再次进入就绪状态才有机会转入运行态,阻塞的三种情况:

          ①等待阻塞:运行的线程执行了wait()方法,JVM将其放入到等待池

          ②同步阻塞:运行的线程在获取锁的时候,被其他线程抢占,JVM会将其放入锁池

          ③其他阻塞:运行的线程执行了sleep()方法或join()方法,或者发出了I/O请求,JVM会把该线程置为阻塞态,这些线程执行结束后,线程会重新转入就绪态

       (5)死亡:线程执行结束或因异常退出了run()方法,该线程结束生命周期

4、start()和run()的区别?

       Start()是启动一个线程(不是立即执行,而是使线程变为可运行态),run()是执行当前线程的方法。调用start()才能实现多线程

5、“不可变”对象?

可变是指变量的值在其生命周期内是可以发生改变的

我们知道不可变的对象一定是线程安全的,并且永远也不需要额外的同步(因为一个不可变的对象只要构建正确,其外部可见状态永远都不会发生改变)。所以可变意味着存在线程不安全的风险。

6、Java中Semaphore是什么?

       Semaphore信号量,是一个计数信号量:通常用于限制可以访问某些资源的数目

临界区:是对多线程的串行化来访问公共资源,在任意时刻只允许一个线程对共享资源进行访问,只有临界区被释放后,其他线程才可以被被抢占

互斥量:用互斥对象机制,只有拥有互斥对象的线程才可以访问公共资源,互斥不仅能实现同一应用程序的公共资源安全,还能实现不同应用程序的公共资源安全共享(互斥锁:Synchronized)

信号量:允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目

事件:通过通知操作的方式来保持线程的同步,还可以方便实现多个线程的优先级比较的操作

       信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在 哪里)。而互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这 个资源

7、解释一下什么是死锁?死锁产生的原因?死锁产生的条件?

       死锁是指两个线程A,B争夺同一资源s,线程A开始执行,线程A需要用到线程B执行完后的结果,这时线程A因需等待B的结果而进入阻塞状态,线程B开始运行,但却无法获取资源s,线程B也进入阻塞状态,此时两个线程处于相持状态,即死锁

8、线程的性质:原子性、可见性、有序性

9、线程调度:调整线程的优先级(默认为5,范围1~10),线程的优先级具有继承关系

10、函数

sleep():线程睡眠,使线程从运行态到阻塞态,睡眠结束后转为就绪态

yield():退让,暂停当前正在执行的线程对象,把执行机会让给相同或者更高的优先级

目的:是让有相同优先级的线程之间能适当的轮转执行,让线程从运行态转至可运行态

Join():线程加入,在当前线程中调用另一个线程的jion方法,则当前线程进入阻塞状态,直至另一个进程运行结束

Wait():线程进入等待,直到其他线程调用此对象的notify()或notifyAll()方法唤醒,等价于wait(0)

Obj.wait(),obj.notify(),必须与synchronized(obj)一起使用,即wait(),notify()只针对已经获取obj锁的进行操作,即wait()是在线程获取对象锁后主动释放对象锁,同时本线程休眠,直到其他线程调用对象的notify()唤醒线程,notify()调用后并不是立马释放锁,而是在synchronized语句块之行结束,自动释放锁。

Notify():线程唤醒,还有notifyAll()该操作唤醒所有线程

Interrupt():中断某个线程,某个资源还未来得及关闭,即run方法还未执行结束,就强行结束线程,会导致资源无法关闭。可以用来中断某个线程,给线程发送一个中断信号,让线程在无限等待时(如死锁)能够抛出异常,从而结束线程;如果你将异常解决,那么就不会中断

*Sleep()和yield()的区别?

       执行sleep()的线程时间未到是不能恢复执行态的,时间确定,较低优先级的线程有机会执行

       而yield()有可能从可执行态又马上被执行,时间不定,只让给高优先级线程执行

*sleep()和wait()的区别?

       Sleep()是将当前线程阻塞,暂停程序,让出CPU,但不释放锁,无法执行同步方法,指定时间到了若无比它优先级高的线程执行就会恢复运行态,否则需等待

       Wait()是让线程进入等待状态,线程会释放锁,其他线程可以调用其同步方法,只有调用notify()方法后本线程才能进入锁定池准备

猜你喜欢

转载自blog.csdn.net/sinat_36722750/article/details/82025226