Java多线程面试知识点汇总(超详细总结)
一、sleep()方法、wait()方法、yeild()方法、interrupt()方法、notify()、notifyAll()方法
1、sleep()方法:
sleep方法为Thread的静态方法;
sleep方法的作用是让线程休眠指定时间,在时间到达时自动恢复线程的执行;
sleep方法不会释放线程锁;
2、wait()方法:
wait方法是Object的方法;
任意一个对象都可以调用wait方法,调用wait方法会将调用者的线程挂起,使该线程进入一个叫waitSet 的等待区域,直到其他线程调用同一个对象的notify
方法才会重新激活调用者;
当wait方法被调用时,它会释放它所占用的锁标记,从而使线程所在对象中的synchronize数据可以被别的线程所使用,
所以wait()方法必须在同步块中使用,notify()和notifyAll()方法都会对对象的“锁标记”进行修改,所以都需要在同步块中进行调用,
如果不在同步块中调用,虽然可以编辑通过,但是运行时会报IllegalMonitorStateException(非法的监控状态异常);
3、yeild()方法:
yeild()方法表示停止当前线程,使该线程进入可执行状态,让同等优先级的线程运行,如果没有同等优先级的线程,那么yeild()方法不
会起作用;
4、notify()和nofityAll()方法;
notify()会通知一个处在wait()状态的线程;如果有多个线程处在wait状态,他会随机唤醒其中一个;
notifyAll()会通知过所有处在wait()状态的线程,具体执行哪一个线程,根据优先级而定;
二、java线程的状态
java线程有四种状态:产生、就绪、执行、阻塞、死亡
产生:线程被创建,但是未启动(未调用start())
就绪:线程被启动(调用start()),处于可执行状态,等待CPU的调度;
执行:线程正常的运行状态;
死亡:一个线程正常执行结束;
阻塞:
(1)、等待阻塞:运行的线程执行wait()方法,jvm会把该线程放入waitSet线程池(释放锁);
(2)、同步阻塞(死锁):运行的线程在获取其他对象的同步锁是,该对象的同步锁被别的线程锁占用,则jvm会将该线程放入线程池中;
(3)、其他阻塞:运行的线程执行sleep方法或者执行t.join()方法,被别的线程打断,jvm把该线程置为阻塞状态,当sleep超时或者join线程结
束时线程重新进入就绪状态
三、java实现多线程的方法:继承Thread类,实现runnable接口,实现Callable接口
1、继承Thread类:
public class MyThread extends Thread { public void run() { System.out.println("MyThread.run()"); } } MyThread myThread1 = new MyThread(); myThread1.start();
2、实现Runnable接口:
public class MyThread immplements Runnable {public void run(){sysout.out.println("MyThread.run()");}}MyThread runThread = new MyThread();Thread runThread = new Thread(runThread,"");runThread.start();
3、实现Callable接口,通过FutureTask包装器创建Thread线程
优缺点:
1)、继承Thread类为单继承,实现Runnable方法为多实现,所以在灵活性上来说,使用实现Runnable方法更灵活;
2)、通过实现Runnable接口的方式可以实现多线程内的资源共享;
3)、增加代码的健壮性,代码可以被多个线程共享,代码和数据独立;
4)、线程池只能放实现Runnable或callable类的线程,不能直接放入继承Thread类的线程;
四、线程调度
1、调整现场优先级:Java线程有优先级,优先级高的线程获得较多的运行机会(运行时间);
static int Max_priority 线程可以具有的最高优先级,值为10;
static int MIN_PRIORIYT 线程可以具有的最低优先级,值为1;
static int NORM_PRIORITY 分配给线程的默认优先级,值为5;
Thread类的setPriority()和getPriority()方法分别用来设置和获取线程的优先级;
2、线程睡眠:Thread.sleep(long millins)使线程转到阻塞状态;
3、线程等待:Object.wait()方法,释放线程锁,使线程进入等待状态,直到被其他线程唤醒(notify()和notifyAll());
4、线程让步:Thread.yeild()方法暂停当前正在执行的线程,使其进入等待执行状态,把执行机会让给相同优先级或更高优先级的线程,如果没有较高优先级
或相同优先级的线程,该线程会继续执行;
5、线程加入:join()方法,在当前线程中调用另一个线程的join()方法,则当前线程转入阻塞状态,知道另一个进程运行结束,当前线程再有阻塞状态转
为就绪状态;
五、线程类的一些常用方法:
1)、sleep():强迫一个线程睡眠N毫秒;
2)、isAlive():判断一个线程是否存活;
3)、join():线程插队;
4)、activeCount():程序中活跃的线程数;
5)、enumerate():枚举程序中的线程;
6)、currentThread():得到当前线程;
7)、isDeamon():一个线程是否为守护线程;
8)、setName():为线程设置一个名字;
9)、wait():线程等待;
10)、notify():唤醒一个线程;
11)、setPriority():设置一个线程的优先级;
六:线程同步
线程同步主要使用synchronized关键字;具体有两种实现方式:1、作为关键字修饰类中一个方法;2、修饰方法中的一块区域(代码);
1、把synchronized当做方法(函数)的修饰符:
public class Name{//类名为Name//getName方法public synchronized void getName(){system.out.println(“123”);}
}
类Name 有两个实例对象n1和n2,此时有两个线程t1和t2;n1在线程t1中执行getName()方法(获得这个方法的锁),那么n1就不能在线程t2中执行getName(
)方法了,但是n2可以在t1线程中执行getName()方法,同理n2 不能同时在t2线程中执行getName()方法;所以说实际上synchronized锁的是getName()
这个方法的对象(n1和n2),而不是锁的这个方法,这个需要理解;
2、同步块,实例代码如下:
public void getName(Object o){synchronized(o){//TODO}}
这里表示锁住这个变量o;
这里做一个线程安全的单例模式
public class Car{//构造方法私有化private Car();//创建一个静态的私有的空的常量carprivate static Car car = null; //对外开放一个静态的共有的方法用来获取实例public static getInstance(){if(car == null){synchronized(Car.getClass()){if(car == null){car = new Car();}} }return car;}
}
七、线程数据传递
在传统的开发模式下,当我们调用一个函数时,通过这个函数的参数将数据传入,并通过这个函数的返回值来返回最终的计算结果,但是在多线程的异步开发
模式下,数据的传递和返回同同步开发模式有很大区别。由于线程的运行和结果是不可预料的,因此在传递和返回数据时就无法像函数一样通过函数参数和
return语句来返回数据;
1、通过构造方法传递参数
package mythread;
public class MyThread1 extends Thread
{
private String name;
public MyThread1(String name)
{
this.name = name;
}
public void run()
{
System.out.println("hello " + name);
}
public static void main(String[] args)
{
Thread thread = new MyThread1("world");
thread.start();
}
}
由于这种方法是在创建线程对象的同时传递数据的,因此,在线程运行之前这些数据就就已经到位了,这样就不会造成数据在线程运行后才传入的现象。如果
要传递更复杂的数据,可以使用集合、类等数据结构。使用构造方法来传递数据虽然比较安全,但如果要传递的数据比较多时,就会造成很多不便。由于Java
没有默认参数,要想实现类似默认参数的效果,就得使用重载,这样不但使构造方法本身过于复杂,又会使构造方法在数量上大增。因此,要想避免这种情况
,就得通过类方法或类变量来传递数据。
2、通过变量和方法传递数据
向对象中传入数据一般有两次机会,第一次机会是在建立对象时通过构造方法将数据传入,另外一次机会就是在类中定义一系列的public的方法或变量(也可
称之为字段)。然后在建立完对象后,通过对象实例逐个赋值。下面的代码是对MyThread1类的改版,使用了一个setName方法来设置 name变量:
package mythread;
public class MyThread2 implements Runnable
{
private String name;
public void setName(String name)
{
this.name = name;
}
public void run()
{
System.out.println("hello " + name);
}
public static void main(String[] args)
{
MyThread2 myThread = new MyThread2();
myThread.setName("world");
Thread thread = new Thread(myThread);
thread.start();
}
}
3、最后是线程之间的数据共享,以下贴出生产者消费者模式的实现:
实现场景:有一个馒头房,生产者生产馒头,消费者消费馒头,当馒头数量为0时要停止消费,开始生产,当生产的馒头大于5时停止生产,开始消费;
分析:
1、馒头类:变量:mt(馒头),num(馒头数量),eatMantou()(吃馒头方法),produceMantou()(生产馒头方法),此处通过构造方法传递对象
2、消费者类:吃馒头,即用来调用馒头对象的吃馒头方法;
3、生产者类:生产馒头,即用来调用馒头对象的生产馒头方法;
4、Test类:用来测试;
具体代码如下:
package com.yp.producerAndconsumer;
/*** @prama 生产者消费者问题中的产品*/
public class Mantou {private String mt;private int num;public String getMt() {return mt;}public void setMt(String mt) {this.mt = mt;}public int getNum() {return num;}public void setNum(int num) {this.num = num;}public Mantou(String mt, int num) {this.mt = mt;this.num = num;}/*** 消费馒头*/public synchronized void eatMantou(){//如果馒头数量大于0,则消费馒头while(num >0){System.out.println("消费后有:---"+this.num+"\n");num--;try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}while(num ==0){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}this.notify();}}/*** 生产馒头*/public synchronized void produceMantou(){while(num<5){System.out.println("生产后有:---"+this.num+"个"+"\n");num ++;try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}}while(num ==5){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}this.notify();}}
}
消费者类;
package com.yp.producerAndconsumer;public class Consumer implements Runnable {private Mantou m ;public Consumer(Mantou m) {this.m = m;}@Overridepublic void run() {m.eatMantou();}
}
生产者类:
package com.yp.producerAndconsumer;public class Producer implements Runnable{Mantou m ;public Producer(Mantou m) {this.m = m;}@Overridepublic void run() {m.produceMantou();}
}
测试类:
package com.yp.producerAndconsumer;/*** @param 生产者消费者问题* @author YangPeng**/
public class ProducerAndConsumer {public static void main(String[] args) {Mantou mantou = new Mantou("花卷",4);Producer producer = new Producer(mantou);Consumer consumer = new Consumer(mantou);Thread t1 = new Thread(producer);Thread t2 = new Thread(consumer);t1.start();t2.start();}
}
Java多线程面试知识点汇总(超详细总结)相关推荐
- 转 :2019年Java大厂面试(吐血超详细总结)
2019年Java大厂面试(吐血超详细总结) 本文来自于慕课网手记:Java大厂面试(吐血超详细总结),转载请保留链接 ;) 转载自:https://www.imooc.com/article/286 ...
- 转:Java多线程学习(吐血超详细总结)
版权声明:本文为博主林炳文Evankaka原创文章,转载请注明出处http://blog.csdn.net/evankaka 目录(?)[+] 林炳文Evankaka原创作品.转载请注明出处http: ...
- (转) Java多线程学习(吐血超详细总结)
林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 写在前面的话:此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但 ...
- Java多线程学习(吐血超详细总结)【转】
林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 目录(?)[-] 一扩展javalangThread类 二实现javalangRunnable ...
- JAVA多线程详解(超详细)
目录 一.线程简介 1.进程.线程 2.并发.并行.串行 3.进程的三态 二.线程实现 1.继承Thread类 2.实现Runnable接口 3.实现Callable接口(不常用) 三.线程常用方法 ...
- 中高级前端面试知识点汇总
1.1.什么是HTML语义化?有什么好处? 根据内容的结构化(内容语义化),选择合适的标签(代码语义化)便于开发者阅读和写出更优雅的代码的同时让浏览器的爬虫和机器很好地解析. 为了在没有 CSS 的情 ...
- Java并发知识总结,超详细!(上)
Java并发知识总结,超详细! 首先给大家分享一个github仓库,上面放了 200多本经典的计算机书籍 ,包括C语言.C++.Java.Python.前端.数据库.操作系统.计算机网络.数据结构和算 ...
- Java多线程面试问题
转载自 Java多线程面试问题 这篇文章主要是对多线程的面试问题进行总结的,罗列了40个多线程的问题. 1.多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用 ...
- 这些Java基础面试知识点,你都掌握了吗?
想了解一下学Java的小伙伴们,在学习Java的时候有没有去总结知识点,哪些知识点我们没有掌握,哪些知识点是我们还没有掌握的,今天小编来发掘一些Java基础面试知识点,不知道大家掌握没有. 小编分享的 ...
- java面试题答案大全超详细(持续更新)
java面试题答案大全超详细 第01章 java语言面试题 项目经理(作者):张明星 JVM 运行时数据区是什么? 程序计数器是什么? 程序计数器(线程私有) Java 虚拟机栈的作用? 本地方法栈的 ...
最新文章
- 600 imp oracle_oracle数据库的导入导出(imp和exp)
- 使用Java8改造出来的模板方法真的是yyds
- qt如何安装python_安装Python QT,PythonQT,的
- hdu 4691 Front compression
- UML统一建模语言第3章 UML建模工具简介课后习题
- vb6.0开发的单片机串口温度采集系统(单片机测温、串口传输、温度曲线显示)
- 03Java常用API-19. Jdk8新增的日期Date API(LocalDateTime,LocalDate,LocalTime,Instant,Period,Duration)
- 给一个DIV的右上解加一个删除按钮
- java计算机毕业设计数字家谱管理系统设计与实现MyBatis+系统+LW文档+源码+调试部署
- Mac下安装与使用Medis
- Open3d 获取渲染和固定视角json文件及读入
- 无法打开到主机的连接。 在端口 23: 连接失败
- 如何安装Java JDK
- java怎么给pr 上字幕_如何给Final Cut Pro快速加字幕(PR也适用)
- 变量 堆栈 损坏问题
- 微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育” 一、教师管理模块
- 在未来,云计算虚拟化的发展趋势是什么?
- spatialreg | 空间滞后模型(SLR)、空间误差模型(SEM)和空间杜宾模型(SDM)的简单形式的R语言实现...
- PDFill PDF Editor Pro 15特殊版(含Carck)
- 查看tomcat进程号,并终止进程