多线程的一些常见问题
2017-09-24 05:15
232 查看
多线程的问题
1.谈谈你对线程和进程的理解?
(1)进程是正在执行的程序
(2)线程进程中用于控制程序执行的控制单元(执行路径)
(3)进程中至少有一个线程,对于JVM,启动时至少有两个线程:JVM的主线程和JVM的垃圾回收线程
2.多线程(多线程并行和并发的区别)
(1)并行就是两个任务同时运行,就是甲任务进行的同时,乙任务也在进行。(需要多核CPU)
(2)并发是指两个任务都请求运行,而处理器只能按受一个任务,就把这两个任务安排轮流进行,由于时间间隔较短,使人感觉两个任务都在运行。
(3)比如我跟两个网友聊天,左手操作一个电脑跟甲聊,同时右手用另一台电脑跟乙聊天,这就叫并行。
(4)如果用一台电脑我先给甲发个消息,然后立刻再给乙发消息,然后再跟甲聊,再跟乙聊。这就叫并发。
3.多线程(两种方式的区别以及两种实现方式的过程)(掌握)
(1)查看源码的区别:
* a.继承Thread : 由于子类重写了Thread类的run(), 当调用start()时, 直接找子类的run()方法
* b.实现Runnable : 构造函数中传入了Runnable的引用, 成员变量记住了它, start()调用run()方法时内部判断成员变量Runnable的引用是否为空,
不为空编译时看的是Runnable的run(),运行时执行的是子类的run()方法
(2)继承Thread
* 好处是:可以直接使用Thread类中的方法,代码简单
* 弊端是:如果已经有了父类,就不能用这种方法
(3)实现Runnable接口
* 好处是:即使自己定义的线程类有了父类也没关系,因为有了父类也可以实现接口,而且接口是可以多实现的
* 弊端是:不能直接使用Thread中的方法需要先获取到线程对象后,才能得到Thread的方法,代码复杂//多线程实现方式
4.sleep和wait的区别?
(1)sleep是让线程休眠,必须给定休眠的时间,时间到了后自动醒来,不需要唤醒,休眠时不放弃cpu的执行权
(2)wait是让线程等待,可以给时间,也可以不等时间,但是必须要唤醒才能醒来(使用notify或者notifyAll),等待时放弃cpu的执行权
(3)sleep方法是Thread类中定义的方法,wait是Object中定义的方法
(4)wait用在同步代码块或者同步方法中,sleep可以在任何地方使用
(5)sleep必须捕获异常,wait不用捕获异常
5.休眠线程、守护线程、加入线程、礼让线程
(1)休眠线程:控制当前线程休眠若干毫秒1秒= 1000毫秒 1秒 = 1000 * 1000 * 1000纳秒 1000000000
(2)守护线程:设置一个线程为守护线程, 该线程不会单独执行, 当其他非守护线程都执行结束后, 自动退出
(3)加入线程:当前线程暂停, 等待指定的线程执行结束后, 当前线程再继续
(4)礼让线程:yield让出cpu
6.同步代码块,同步方法,静态同步方法的区别?以及什么时候使用同步?
* 当多线程并发, 有多段代码同时执行时, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作. 这时就需要同步.
* 如果两段代码是同步的, 那么同一时间只能执行一段, 在一段代码没执行结束之前, 不会执行另外一段代码.
(1).多线程操作共享数据
(2).有多条语句在操作共享数据
(3).要使用同一个锁
(4)同步代码块可以使用任意对象作为锁对象,同步方法的锁为this,静态同步方法的锁为所在类的字节码对象
7.什么是死锁?举例说明?
解释:两个线程,各自拿着自己的锁,而又想获取对方的锁,而双方谁都不让,就会出现死锁
多线程同步的时候, 如果同步代码嵌套, 使用相同锁, 就有可能出现死锁
举例:
(1)两个人上厕所,而厕所有两把锁
(2)还有上课讲的两根筷子的故事
8.设计模式?
(1)包装设计模式(*****)
(2)模板设计模式(***)
(3)工厂设计模式(*****)
(4)单例设计模式(*****)
/*
* 饿汉式和懒汉式的区别
* 1,饿汉式是空间换时间,懒汉式是时间换空间
* 2,在多线程访问时,饿汉式不会创建多个对象,而懒汉式有可能会创建多个对象
*/
(5)动态代理设计模式(*****)
(6)适配器设计模式
9.说一下你所学过的线程安全的类?
(1)看源码:Vector,StringBuffer,Hashtable,Collections.synchroinzed(xxx)
(2)Vector是线程安全的,ArrayList是线程不安全的
(3)StringBuffer是线程安全的,StringBuilder是线程不安全的
(4)Hashtable是线程安全的,HashMap是线程不安全的
10.说一下你对线程间的通信的理解?
(1)什么时候需要通信
* 多个线程并发执行时, 在默认情况下CPU是随机切换线程的
* 如果我们希望他们有规律的执行, 就可以使用通信, 例如每个线程执行一次打印
(2)怎么通信
* 如果希望线程等待, 就调用wait()
* 如果希望唤醒等待的线程, 就调用notify();
* 这两个方法必须在同步代码中执行, 并且使用同步锁对象来调用
(3)多个线程通信的问题
* notify()方法是随机唤醒一个线程
* notifyAll()方法是唤醒所有线程
* JDK5之前无法唤醒指定的一个线程
* 如果多个线程之间通信, 需要使用notifyAll()通知所有线程, 用while来反复判断条件
11.Runtime类,Timer类,互斥锁(*******ReentrantLock)?
12.线程组的概念?线程池的概念?
线程组:
线程组存在的意义,首要原因是安全。
java默认创建的线程都是属于系统线程组,而同一个线程组的线程是可以相互修改对方的数据的。
但如果在不同的线程组中,那么就不能“跨线程组”修改数据,可以从一定程度上保证数据安全.
线程池:
线程池存在的意义,首要作用是效率。
线程的创建和结束都需要耗费一定的系统时间(特别是创建),不停创建和删除线程会浪费大量的时间。所以,在创建出一条线程并使其在执行完任务后不结束,而是使其进入休眠状态,在需要用时再唤醒,那么 就可以节省一定的时间。
如果这样的线程比较多,那么就可以使用线程池来进行管理。保证效率。
线程池在系统启动时即创建大量空闲的线程,程序将一个Runnable对象或Callable对象传给线程池,线程池就会启动一个线程来执行它们的run()或call()方法,当执行完毕后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个任务。
线程组和线程池共有的特点:
1,都是管理一定数量的线程
2,都可以对线程进行控制---包括休眠,唤醒,结束,创建,中断(暂停)--但并不一定包含全部这些操作。
13.线程的5种状态?(必须掌握,详细的请参考图片)
(1)新建 new
(2)就绪 start()
(3)运行 run()或call()
(4)阻塞 sleep() wait()
(5)死亡 1) run方法正常退出而自然死亡,
2) 一个未捕获的异常终止了run方法而使线程猝死。
14.线程实现的第三种方式?-Callable
1.谈谈你对线程和进程的理解?
(1)进程是正在执行的程序
(2)线程进程中用于控制程序执行的控制单元(执行路径)
(3)进程中至少有一个线程,对于JVM,启动时至少有两个线程:JVM的主线程和JVM的垃圾回收线程
2.多线程(多线程并行和并发的区别)
(1)并行就是两个任务同时运行,就是甲任务进行的同时,乙任务也在进行。(需要多核CPU)
(2)并发是指两个任务都请求运行,而处理器只能按受一个任务,就把这两个任务安排轮流进行,由于时间间隔较短,使人感觉两个任务都在运行。
(3)比如我跟两个网友聊天,左手操作一个电脑跟甲聊,同时右手用另一台电脑跟乙聊天,这就叫并行。
(4)如果用一台电脑我先给甲发个消息,然后立刻再给乙发消息,然后再跟甲聊,再跟乙聊。这就叫并发。
3.多线程(两种方式的区别以及两种实现方式的过程)(掌握)
(1)查看源码的区别:
* a.继承Thread : 由于子类重写了Thread类的run(), 当调用start()时, 直接找子类的run()方法
* b.实现Runnable : 构造函数中传入了Runnable的引用, 成员变量记住了它, start()调用run()方法时内部判断成员变量Runnable的引用是否为空,
不为空编译时看的是Runnable的run(),运行时执行的是子类的run()方法
(2)继承Thread
* 好处是:可以直接使用Thread类中的方法,代码简单
* 弊端是:如果已经有了父类,就不能用这种方法
(3)实现Runnable接口
* 好处是:即使自己定义的线程类有了父类也没关系,因为有了父类也可以实现接口,而且接口是可以多实现的
* 弊端是:不能直接使用Thread中的方法需要先获取到线程对象后,才能得到Thread的方法,代码复杂//多线程实现方式
//多线程实现方式 //1.继承Thread class MyThread extends Thread{ @Override public void run() { //得到当前线程的名字 String name = Thread.currentThread().getName(); Log.d("MainActivity","Thread线程的名字:"+name); } } //启动线程 new MyThread().start(); //2.s实现Runnable接口 class MyRunnable implements Runnable{ @Override public void run() { //得到当前线程的名字 String name = Thread.currentThread().getName(); Log.d("MainActivity","Runnable线程的名字:"+name); } } //启动线程 new Thread(new MyRunnable()).start();
4.sleep和wait的区别?
(1)sleep是让线程休眠,必须给定休眠的时间,时间到了后自动醒来,不需要唤醒,休眠时不放弃cpu的执行权
(2)wait是让线程等待,可以给时间,也可以不等时间,但是必须要唤醒才能醒来(使用notify或者notifyAll),等待时放弃cpu的执行权
(3)sleep方法是Thread类中定义的方法,wait是Object中定义的方法
(4)wait用在同步代码块或者同步方法中,sleep可以在任何地方使用
(5)sleep必须捕获异常,wait不用捕获异常
5.休眠线程、守护线程、加入线程、礼让线程
(1)休眠线程:控制当前线程休眠若干毫秒1秒= 1000毫秒 1秒 = 1000 * 1000 * 1000纳秒 1000000000
(2)守护线程:设置一个线程为守护线程, 该线程不会单独执行, 当其他非守护线程都执行结束后, 自动退出
(3)加入线程:当前线程暂停, 等待指定的线程执行结束后, 当前线程再继续
(4)礼让线程:yield让出cpu
6.同步代码块,同步方法,静态同步方法的区别?以及什么时候使用同步?
* 当多线程并发, 有多段代码同时执行时, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作. 这时就需要同步.
* 如果两段代码是同步的, 那么同一时间只能执行一段, 在一段代码没执行结束之前, 不会执行另外一段代码.
(1).多线程操作共享数据
(2).有多条语句在操作共享数据
(3).要使用同一个锁
(4)同步代码块可以使用任意对象作为锁对象,同步方法的锁为this,静态同步方法的锁为所在类的字节码对象
7.什么是死锁?举例说明?
解释:两个线程,各自拿着自己的锁,而又想获取对方的锁,而双方谁都不让,就会出现死锁
多线程同步的时候, 如果同步代码嵌套, 使用相同锁, 就有可能出现死锁
举例:
(1)两个人上厕所,而厕所有两把锁
(2)还有上课讲的两根筷子的故事
8.设计模式?
(1)包装设计模式(*****)
(2)模板设计模式(***)
(3)工厂设计模式(*****)
(4)单例设计模式(*****)
/*
* 饿汉式和懒汉式的区别
* 1,饿汉式是空间换时间,懒汉式是时间换空间
* 2,在多线程访问时,饿汉式不会创建多个对象,而懒汉式有可能会创建多个对象
*/
(5)动态代理设计模式(*****)
(6)适配器设计模式
9.说一下你所学过的线程安全的类?
(1)看源码:Vector,StringBuffer,Hashtable,Collections.synchroinzed(xxx)
(2)Vector是线程安全的,ArrayList是线程不安全的
(3)StringBuffer是线程安全的,StringBuilder是线程不安全的
(4)Hashtable是线程安全的,HashMap是线程不安全的
10.说一下你对线程间的通信的理解?
(1)什么时候需要通信
* 多个线程并发执行时, 在默认情况下CPU是随机切换线程的
* 如果我们希望他们有规律的执行, 就可以使用通信, 例如每个线程执行一次打印
(2)怎么通信
* 如果希望线程等待, 就调用wait()
* 如果希望唤醒等待的线程, 就调用notify();
* 这两个方法必须在同步代码中执行, 并且使用同步锁对象来调用
(3)多个线程通信的问题
* notify()方法是随机唤醒一个线程
* notifyAll()方法是唤醒所有线程
* JDK5之前无法唤醒指定的一个线程
* 如果多个线程之间通信, 需要使用notifyAll()通知所有线程, 用while来反复判断条件
11.Runtime类,Timer类,互斥锁(*******ReentrantLock)?
12.线程组的概念?线程池的概念?
线程组:
线程组存在的意义,首要原因是安全。
java默认创建的线程都是属于系统线程组,而同一个线程组的线程是可以相互修改对方的数据的。
但如果在不同的线程组中,那么就不能“跨线程组”修改数据,可以从一定程度上保证数据安全.
线程池:
线程池存在的意义,首要作用是效率。
线程的创建和结束都需要耗费一定的系统时间(特别是创建),不停创建和删除线程会浪费大量的时间。所以,在创建出一条线程并使其在执行完任务后不结束,而是使其进入休眠状态,在需要用时再唤醒,那么 就可以节省一定的时间。
如果这样的线程比较多,那么就可以使用线程池来进行管理。保证效率。
线程池在系统启动时即创建大量空闲的线程,程序将一个Runnable对象或Callable对象传给线程池,线程池就会启动一个线程来执行它们的run()或call()方法,当执行完毕后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个任务。
线程组和线程池共有的特点:
1,都是管理一定数量的线程
2,都可以对线程进行控制---包括休眠,唤醒,结束,创建,中断(暂停)--但并不一定包含全部这些操作。
13.线程的5种状态?(必须掌握,详细的请参考图片)
(1)新建 new
(2)就绪 start()
(3)运行 run()或call()
(4)阻塞 sleep() wait()
(5)死亡 1) run方法正常退出而自然死亡,
2) 一个未捕获的异常终止了run方法而使线程猝死。
14.线程实现的第三种方式?-Callable
//Callable接口实现多线程 class MyCallable implements Callable<Integer>{ @Override public Integer call() throws Exception { //得到当前线程的名字 String name = Thread.currentThread().getName(); Log.d("MainActivity","Callable线程的名字:"+name); return 100; } } //main方法中启动多线程 MyCallable myCallable = new MyCallable(); FutureTask<Integer> task = new FutureTask<>(myCallable); new Thread(task).start();//启动Callable方式实现的线程 Integer integer = 0; try { //call()方法的返回值 integer = task.get(); } catch (Exception e) { e.printStackTrace(); }finally { Log.d("MainActivity","call()的返回值:"+integer); }
相关文章推荐
- 黑马程序员---java多线程的一些常见问题
- 在决定使用ClickOnce发布你的软件前,应该知道的一些事情(一些常见问题解决方法)
- android fragment中一些常见问题
- 发布项目到中央库的一些常见问题
- [转]SQL SERVER中一些常见性能问题的总结
- 多线程常见问题
- 缓存中常见的一些问题
- 对VC++一些常见问题的整理
- ie与火狐中常见的一些兼容问题
- EXCEL中一些常见的问题
- java多线程常见问题及基础知识
- VC 和 MFC 的一些常见问题
- vim一些最常见的问题(FAQ)
- .NET中一些常见代码的性能问题
- 面试中常见的一些算法问题
- SQL Server中一些常见的性能问题
- Jquery一些常见性能的问题
- MFC一些常见面试问题
- 关于多线程学习遇到的一些问题
- CSS(1)-常见的一些问题解答