多线程
进程和线程的区别是什么?
进程是执行着的应用程序,而线程是进程内部的一个执行序列.一个进程可以有多个线程.线程又叫做轻量级进程.
创建线程有几种方式?
有三种方式:
继承Thread类
实现Runnable接口
应用程序可以使用Executor框架来创建线程池
实现Runnable接口这种方式更受欢迎,因为这不需要继承Thread类,在应用设计中已经继承了别的对象的情况下,这需要多继承(而java不支持多继承),只能实现接口.同时,线程池也是非常高效的,很容易实现和使用.
概括的解释下线程的几种可用状态?
1新建(new):新创建了一个线程对象
2.可运行(runnable):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法,该状态的线程位于可运行线程池由线程调度选中,获取cpu的使用权.
3.运行(running):可运行状态(runnable)的线程获得了cpu的时间片(timeslice),执行程序代码
4.阻塞(block):阻塞状态是指线程因为某种原因放弃了cpu使用权,也即让出了cpu timeslice,暂时停止运行.直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice,转到(running)状态,阻塞分为三种:
1.等待阻塞:运行(running)的线程在获取对象的同步锁时,JVM会把该线程放入等待队列(waitting queue)中
2.同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则jvm会把该线程放入锁池(lock pool)中
3.其他阻塞:运行(running)的线程执行Thread sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态.当sleep()状态超时,join()等待线程终止或者超时,或者I/O处理完毕时,线程重新转入可运行(runnable)状态
5.死亡(dead):线程run().main()方法执行结束,或者因异常退出了run()方法,则该线程结束声明周期.死亡的线程不可再次复生.
举例:早上乘坐出租车
新建:(已经联系到了一辆出租车)
可运行(出租车找到了你,上车)
运行(司机带你去上班的路上)
阻塞(路上出现堵车)
死亡(到公司,付钱下车,结束乘车.)
同步方法和同步代码快的区别是什么?
同步方法默认使用this或者当前类class对象作为锁
同步代码块可以选择以什么来加锁,比同步方法要更加细颗粒度,我们可以选择只同步会发生同步稳步的部分代码而不是整个方法.
什么是死锁?
两个线程或者两个以上线程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁,结果就是这些线程都陷入了无限的等待中.
如何确保N个线程可以访问N个资源同时又不导致死锁?
使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁.因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了.
sleep()和wait()的区别?-
sleep指线程被调用时,占着cpu不工作,形象的说明为"睡觉",此时,系统的CPU部分资源被占用,其他线程无法进入,会增加时间限制.
wait指线程处于进入等待状态,形象地说明为"等待使用CPU",此时线程不占用任何资源,不增加时间限制.
实现同步的方式?
同步是多线程中的重要概念.同步的使用可以保证在多线程运行的环境中,程序不会产生设计之外的错误结果.同步的实现方式有两种,同步方法和同步块.这两种方式都要用到synchronized关键字.
1.同步方法
即有synchronized关键字修饰的方法.
由于java的每个对象都有一个内置锁,当用此关键字修饰方法时.
内置锁会保护整个方法.在调用该方法时,需要获得内置锁,否则就处于阻塞状态.
代码如:
public synchronized void save(){}
注:synchronize关键字也可以修饰静态方法,此时如果调用该静态方法.将会锁住整个类
2.同步代码块
即有synchronized关键字修饰的语句块
被该关键字修饰的语句快会自动被加上内置锁,从而实现同步
比如:
synchronized(object){}
注:同步是一种高开销的操作,因此应该尽量减少同步的内容.
通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可.
本文来自博客园,作者:King-DA,转载请注明原文链接:https://www.cnblogs.com/qingmuchuanqi48/p/10772243.html