解决Java多线程中11个常见问题
- 格式:docx
- 大小:26.21 KB
- 文档页数:6
解决Java多线程中11个常见问题
1、线程是什么?
简单来说,线程是进程中独立运行的子任务。
2、创建线程的方式
方式一:将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法
方式二:声明实现 Runnable 接口的类。该类然后实现 run 方法
推荐方式二,因为接口方式比继承方式更灵活,也减少程序间的耦合。
3、获取当前线程信息?
Thread.currentThread()
4、线程的分类
线程分为守护线程、用户线程。线程初始化默认为用户线程。
setDaemon(true) 将该线程标记为守护线程或用户线程。
特性:设置守护线程,会作为进程的守护者,如果进程内没有其他非守护线程,那么守护线程也会被销毁,即使可能线程内没有运行结束。
5、线程的生命周期
线程是一个动态执行的过程,它也有一个从产生到死亡的过程。生命周期的五种状态:
新建(new Thread):当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。
例如:Thread t1=new Thread();
就绪(runnable):线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t1.start();
运行(running):线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。
死亡(dead):当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。
堵塞(blocked):由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。
6、线程间的关系?
某线程a 中启动另外一个线程 t,那么我们称线程 t是线程a 的一个子线程,而线程a 是线程t 的父线程。
最典型的就是我们在main方法中启动一个线程去执行。其中main方法隐含的main线程为父线程。
7、线程API一览:如何启动、停止、暂停、恢复线程?
(1)start() 使线程处于就绪状态,Java虚拟机会调用该线程的run方法;
(2)stop() 停止线程,已过时,存在不安全性,原因如下:
一是可能请理性的工作得不得完成;
二是可能对锁定的对象进行“解锁”,导致数据不同步不一致的情况。
推荐使用 interrupt() +抛异常中断线程。
(3)yield() 线程礼让,放弃当前线程的CPU资源。放弃时间不确认,也有可能刚刚放弃又获得CPU资源。
(4)t.join() 正在执行t.join()语句的线程等待t线程运行完终止。
8、synchronized关键字用法
一原子性(互斥性):实现多线程的同步机制,使得锁内代码的运行必需先获得对应的锁,运行完后自动释放对应的锁。
二内存可见性:在同一锁情况下,synchronized锁内代码保证变量的可见性。
三可重入性:当一个线程获取一个对象的锁,再次请求该对象的锁时是可以再次获取该对象的锁的。
如果在synchronized锁内发生异常,锁会被释放。
总结:
(1)synchronized方法与synchronized(this) 代码块锁定的都是当前对象,不同的只是同步代码的范围
(2)synchronized (非this对象x) 将对象x本身作为“对象监视器”:
a、多个线程同时执行 synchronized(x) 代码块,呈现同步效果。
b、当其他线程同时执行对象x里面的 synchronized方法时,呈现同步效果。
c、当其他线程同时执行对象x里面的 synchronized(this)方法时,呈现同步效果。(3)静态synchronized方法与synchronized(calss)代码块锁定的都是Class锁。Class 锁与对象锁不是同一个锁,两者同时使用情况可能呈异步效果。
(4)尽量不使用synchronized(string),是因为string的实际锁为string的常量池对象,多个值相同的string对象可能持有同一个锁。
9、ReentrantLock的使用
一个简单的示例:
private java.util.concurrent.locks.Lock lock = new ReentrantLock();
public void method() {
try {
lock.lock();
//获取到锁lock,同步块
} finally {
lock.unlock();//释放锁lock
}
}
ReentrantLock 比 synchronized 功能更强大,主要体现:
(1)ReentrantLock 具有公平策略的选择。
(2)ReentrantLock 可以在获取锁的时候,可有条件性地获取,可以设置等待时间,很有效地避免死锁。
如 tryLock() 和tryLock(long timeout, TimeUnit unit)
(3)ReentrantLock 可以获取锁的各种信息,用于监控锁的各种状态。
(4)ReentrantLock 可以灵活实现多路通知,即Condition的运用。
10、线程间的通信方式
线程间通信的方式主要为共享内存、线程同步。
线程同步除了synchronized互斥同步外,也可以使用wait/notify实现等待、通知的机制。(1)wait/notify属于Object类的方法,但wait和notify方法调用,必须获取对象的对象级别锁,即synchronized同步方法或同步块中使用。
(2)wait()方法:在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,或者其他某个线程中断当前线程,导致当前线程一直阻塞等待。等同wait(0)方法。