线程Thread

 ̄綄美尐妖づ 提交于 2020-01-30 15:30:38

什么是线程?

线程是操作系统能够进行运算调度的最小单位,被包含在进程中。线程也叫作轻量级进程,在一个进程里可以创建多个线程,每个线程都有独立的计数器,堆,栈和局部变量,并且能够访问共享的内存变量

 

线程和进程的区别?

线程是一个轻量级进程,一个进程可以有多个线程,各条线程能够执行不同的任务,不同的进程使用不同的内存空间,而所有的线程共享相同的内存空间

 

如何在java中实现线程?

在语言层面有两种方式。Thread类的一个实例就是一个线程,但是需要调用Runnable接口来执行,由于线程类本身就是调用的Runnable接口,所以可以继承Thread类或者直接调用Runnable接口来重写run()方法实现线程

 

Runnable还是Thread?

由于java是单继承的,如果一个类继承了另一个类,再想实现多线程,这时候再继承Thread是不行的,因为这样就是多继承了,可是java不允许,所以如果要继承其他类,那么实现Runnable接口吧(java不能多继承,但是能实现多个接口啊)

并且Runnable适合于资源的共享   因为线程是独立的,所以局部变量不共享,而如果是实现Runnable接口,那么在开一个新线程new Thread(myRunnable,"线程的名字")时,所有的线程都共享接口内的资源(实现了Runnable接口的类的资源)

所以多线程主要以实现Runnable接口为主

 

为什么要使用多线程?

1)更多的处理器核心 : 随着cpu数量的增加,计算机更加擅长并行计算。一个程序作为一个进程,能创建多个线程,而一个时刻一个处理器只能运行一个线程,如果是单线程的话,再多的处理器也没用户,而使用多线程,能够同时利用多个处理器,提高执行效率

2)更快的响应时间: 将数据一致性不强的操作交给其他线程处理,优先响应用户的请求,缩短响应时间,提高用户体验

3)更好的编程模型 : java为多线程编程提供了良好的编程模型

 

 

线程如何调度的?

操作系统分出时间片,线程获得时间片,当线程的时间片用完后发生线程调度,并等待下次分配的时间片。线程获得的时间片的多少决定了线程使用处理器资源的多少,线程优先级就是决定线程分配多少时间片的属性

注意:线程优先级不能作为程序正确性的依赖,因为操作系统可以完全不理会线程优先级

 

Thread类中的start()和run()方法的区别?

start()方法被用来启动新创建的线程,而且start()也是调用的run()方法,但是和直接调用run()不一样,当你调用run()方法时,只会在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程

 

start()?

start()方法将线程的状态由new变为Runnable,只是创建一个线程时,它会处于new状态,不会运行,只有调用start()方法后才会运行(start()方法的调用顺序不能决定线程的执行顺序,取决于jvm的调度算法)

注意:在线程的生命周期中,new->Runnable只会发生一次,因此,一个线程只能调用一次start()方法

 

run()?

run()方法只是一个普通的方法,只不过当线程调用了start()方法后,一旦线程被cpu调度,处于运行状态,线程才会去调用run()方法

run()方法的执行是不需要线程调用start()方法的,run()是一个普通的对象方法,所以线程可以随时调用run()方法,及时线程没有start()

创建两个线程后如果没有start(),而是直接run(),那么两个线程是顺序执行的(即实现并发的是Thread而不是run())

 

 

怎么理解Thread?

Thread也是一个java对象,只不过每个对象都对应一个线程,当一个线程结束,对应的Thread对象还能都用除了start()外的所有其他方法

 

Runnable和Callable的区别?

Runnable和Callable都代表那些要在不同线程中执行的任务,主要区别是Callable的call()方法可以返回值和抛出异常,Callable可以返回装有计算结果的Future对象

 

CyclicBarrier和CountDownLatch的区别?

CountDownLatch是一个线程等到另外N个线程执行完成之后才开始执行,CountDownLatch的await()方法会阻塞当前线程直到N变成0.CountDownLatch不能重用,既不能重新初始化或修改内部的计数器

CyclicBarrier可循环使用(重用),它要做的事情是让一组线程到达一个屏障(同步点)时被阻塞,直到最后一个线程到达屏障点时,所有被阻塞的线程再运行。如果没有调用足够次数的await()方法,则调用了await()方法的线程都会被阻塞

CyclicBarrier有个更高级的构造函数CyclicBarrier(int parts,Runnable barrierAction),会优先执行barrierAction

 

CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset()重置

 

java中的volatile?

volatile变量保证下一个读取操作会在前一个写操作之后发生

 

总结

1)wait()和notify/notifyAll()方法

wai()方法:

   线程进入waiting状态并且释放它所占有的锁标志,从而使别的线程有机会抢夺该锁,等到其他线程调用对象的notify或notifyAll()方法恢复

  wait()方法是一个本地方法,底层是通过一个叫做监视器锁的对象来完成的

notify/notifyAll()方法

   在同一个对象上调用notify/notifyAll方法,就可以唤醒对应对象上等待的线程了,notify只能随机唤醒monitor上的一个线程,而notifyAll是唤醒所有的线程

 

sleep/yield/join ?

sleep:

  sleep方法的作用是让当前线程暂停指定的时间

 wait方法依赖于同步,而sleep可以直接调用

 sleep只是暂时让出cpu的执行权,并不释放锁,而wait需要释放锁

yield:

  yield方法的作用是暂停当前线程,以便其他线程有机会执行,不过不能暂停指定的时间,也不能保证当前线程马上停止

  yield只能使同步优先级或更高优先级的线程有执行的机会

join

  等待调用join方法的线程结束,再继续执行

  作业是父线程等待子线程执行完成后再执行

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!