进程和线程之间的区别
经典问题: 进程和线程到底有那些区别。
可以总结为以下几点:
一个进程可以拥有多个线程,而线程不可以拥有多个进程。
每个进程都拥有自己的内存空间,可执行代码和唯一进程标识符(PID).每个线程都拥有它的栈内存,但它与其他的线程共享当前进程的主内存。
线程也称为任务或者轻量级进程。
创建线程和创建进程也有很大的区别,创建线程就简单的new一个即可,创建进程的话需要通过对父进程的复制来实现。
来自同一线程的进程可以通过使用java编程语言中的wait()和notify()等来进行通信,比进程之间的通信要简单很多。
作为同一进程下的多个线程,可以共享系统资源(如文件描述符,堆内存等),但是在java中,每个线程都拥有自己的栈内存和异常处理程序(所以一个线程抛出异常,不会影响其他线程,具体过程可以自己写程序查jvisualvm)。
wait(),sleep()和yield()之间的区别
第一点不同,wait()是Object类自带的方法,而sleep()和yield()是Thread类定义的方法。
首先来谈wait()和sleep()的区别,wait是用于进程通信的,如果一个线程使用了wait(),那么该线程会释放所拥有的锁和监视器并加入等待队列,其他线程继续争抢锁的所有权。而sleep()是不会释放当前线程所占有的锁和监视器的,该线程只会进行一段时间的暂停
后继续运作。
而对于yield(),它只是释放了当前线程所占有的CPU,以便给另外的线程提供一个运行的机会,但不保证谁将获得CPU。它完全依赖于线程调度程序,调用yield()方法的线程甚至可能再次获得CPU。sleep()也是释放占有的CPU(当前正在执行的线程停止执行并放弃CPU以允许线程调度程序将CPU分配给另一个线程或相同的线程),一般来说,sleep()比yield()更加可靠,应该尽量选择sleep()而不是选择yield()。还有就是sleep()可以被打断,但是yield不可以。
如何检查某个线程持有特定对象的锁
在Thread中,静态方法holdsLock即可完成该功能。例子如下:
public class HoldLockTest {
@Test
public void test() throws InterruptedException {
final Object o=new Object();
new Thread(()->{
synchronized (o){
System.out.println(Thread.currentThread().getName()+" holdLock: "+Thread.holdsLock(o));
}
} ).start();
synchronized (o){
System.out.println(Thread.currentThread().getName()+" holdLock: "+Thread.holdsLock(o));
}
System.out.println(Thread.currentThread().getName()+" holdLock: "+Thread.holdsLock(o));
}
/*
main holdLock: true
main holdLock: false
Thread-0 holdLock: true
*/
}