1.如何停止一个正在运行的线程
- 使用退出标志,使线程正常退出,也就是当run方法完成后线程终止
- 使用stop 方法强行终止
- 使用interrupt打断线程
2.线程中sleep和wait有什么区别?
相同点:sleep和wait都是用来控制线程的
不同点:
- sleep是Thread类(自控)中的方法,wait是Object (他控)中的方法
- sleep可以在任何地方使用,wait只能在synchronized方法或者synchronized使用
- 调用sleep方法,会让出cpu,不会导致锁行为的改变;调用wait方法,不仅会让出cpu,还是释放已经占有的同步资源锁
3.启动一个线程是用run()还是start()?
启动线程是start(),线程启动后就会处于可运行状态,但不一定马上执行run()方法,当cpu分配给它时间时,才开始执行run()方法,start方法调用run方法,run方法是你要重写的程序逻辑,run方法包含的是线程的主体。
4.如何保证线程的运行安全?
- 原子性:提供互斥访问,同一时刻只能由一个线程对数据进行操作。
- 可见性:一个线程对主内存的修改可以及时被其他线程看到
- 有序性:一个线程观察其他线程中的指令执行顺序,由于指令重排序,该观察结果一般杂乱无序。
5.线程同步的几种方法:
- 使用synchronized关键字
- wait和notify方法
- 使用特殊域变量volatile实现线程同步
- 使用可重入锁实现线程同步
- 使用阻塞队列实现线程同步‘
- 使用信号量semaphone
6.创建线程的方法:
- 继承Thread类
- 实现Runnable接口
- 通过Callable和Future创建线程
- 通过线程池创建线程
7.Runnable和Callable区别:
- Runnable接口中的run方法的返回值是void,即没有返回值,纯碎是执行run方法中的代码
- Callable接口中的call方法的返回值是一个Object泛型,和Future,FutureTask配合可以用来获取异步执行的结果。
8.ThreadLocal类使用:
每一个线程独享一个ThreadLocal,在接受请求时set特定的内容,在需要的时候get这个值.如:
public class HostHolder {
private ThreadLocal<User> users = new ThreadLocal<>();
public void setUser(User user) {
users.set(user);
}
public User getUser() {
return users.get();
}
public void clear(){
users.remove();
}
}
- set方法是用来设置当前线程中变量的副本
- get方法是用来获取ThreadLocal在当前线程中保存的变量的副本。
- remove方法用来移除当前线程中变量的副本
- clear方法用来清空当前线程保存的变量的副本
- 此外还有initialValue方法,一般用来在使用时进行重写。如果在没有set的时候就调用get,会自动调用initialValue方法初始化内容
9.为什么要使用线程池:
线程池主要提供了一种限制和管理资源的方式,每个线程池还维护了一些基本统计信息,例如:已完成任务的数量.
使用线程的优点:
- 降低资源的消耗:通过重复利用已经创建的线程降低线程创建和销毁造成的消耗;
- 提高响应速度:当任务到达时,任务可以不需要等到线程创建就能立即执行;
- 提高线程的可管理性:使用线程池可以进行统一的分配,调优,和监控
10.如何创建线程池:
- 通过ThreadPoolExecutor的构造方法实现
- 通过Executor框架的工具类Executor来实现,该工具类提供三种类型的ThreadPoolExecutor:
- FixedThreadPool: 该方法返回一个固定线程池数量的线程池,该线程池中的线程数量始终不变。
- SingleThreadExecutor : 该方法返回一个只有一个线程的线程池。
- CachedThreadPool:该方法返回一个只有一个可根据实际情况调整,即线程池的线程数量不确定,但若有空闲的线程可以复用,优先使用可复用的线程。