线程创建的三种方式及锁

线程和进程是什么?

线程是操作系统能够进行运算调度的最小单位,他被包含在进程之中。

进程是计算机系统进行资源分配和调度的基本单位,一个进程中可以有多个线程。

 

 

线程的状态分为几个过程

1.新建(NEW):新创建了一个线程对象。

2.可运行(RUNNABLE):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。

3.运行(RUNNING):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。
4.阻塞(BLOCKED):阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。

5. 死亡(DEAD):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。

 

 

阻塞又分为哪几种

阻塞的情况分三种:

(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
(二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
(三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。

 

 

3.线程阻塞方法

线程有2种阻塞方法,分别为wait()、sleep(),唤醒的方法为notify()和notifyAll(),interrupt()。

wait():使线程处于一种等待状态,释放所持有的对象锁。

sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用它时要捕获InterruptedException异常,不释放对象锁。

notify():唤醒一个正在等待状态的线程。注意调用此方法时,并不能确切知道唤醒的是哪一个等待状态的线程,是由JVM来决定唤醒哪个线程,不是由线程优先级决定的。

notifyAll():唤醒所有等待状态的线程,注意并不是给所有唤醒线程一个对象锁,而是让它们竞争。

interrupt():用于打断正在睡眠的线程。

 

sleep()和wait()有什么区别?

  1. sleep()方法是Thread的静态方法,wait则是Object的方法。任何对象的实例都能调用。
  2. sleep()方法调用的时候不会释放锁,也不会占用锁,wait()会释放锁,但调用他的前提是必须被synchronized所包围
  3. 他们都可以被interrupt()所打断

 

 

创建线程的方法有那些

  1. 继承Thread重写run()方法,

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAVFlYUEM=,size_20,color_FFFFFF,t_70,g_se,x_16

 

 

  1. 实现Runnable接口重写run()方法

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAVFlYUEM=,size_20,color_FFFFFF,t_70,g_se,x_16

 

 

  1. 实现callable接口

 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAVFlYUEM=,size_20,color_FFFFFF,t_70,g_se,x_16

 

 

实现Runnable接口相比继承Thread类有如下优势:

  1. 可以避免由于Java的单继承特性而带来的局限;
  2. 增强程序的健壮性,代码能够被多个线程共享,代码与数据是独立的;
  3. 适合多个相同程序代码的线程区处理同一资源的情况。

 

实现Runnable接口和实现Callable接口的区别:

  1. Runnable是自从java1.1就有了,而Callable是1.5之后才加上去的
  2. Callable规定的方法是call(),Runnable规定的方法是run()
  3. Callable的任务执行后可返回值,而Runnable的任务是不能返回值(是void)
  4. call方法可以抛出异常,run方法不可以
  5. 运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。
  6. 加入线程池运行,Runnable使用ExecutorService的execute方法,Callable使用submit方法。

 

 

Lock和synchronized的选择

① Lock是一个接口, 而synchronized是Java中的关键字,synchronized是内置的语言实现;
② synchronized在发生异常时, 会自动释放线程占有的锁,因此 不会导致死锁现象发生; 而Lock在发生异常时,如果没有主动通过 unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;
③ Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;(I/O和Synchronized都能相应中断,即不需要处理interruptionException异常)
④ 通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
⑥ Lock可以提高多个线程进行读操作的效率。
在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值