最简单Java程序包含有哪些线程?
代码为证:
/**
* Created by Genge on 2016-06-07.
*/
public class MultiThread {
public static void main(String[] args) {
ThreadInfo[] threadInfos = ManagementFactory.getThreadMXBean().dumpAllThreads(false, false);
for (ThreadInfo threadInfo : threadInfos){
System.out.println("[" + threadInfo.getThreadId() + "]" + threadInfo.getThreadName());
}
}
}
效果图:
[10]Monitor Ctrl-Break
[5]Attach Listener //添加事件
[4]Signal Dispatcher // 分发处理给JVM信号的线程
[3]Finalizer //调用对象finalize方法的线程
[2]Reference Handler //清楚reference线程
[1]main //main线程,程序入口
Process finished with exit code 0
可以看到一个Java
程序的运行不仅仅是main()的方法的运行,而是多线程同时运行!
Thread.yield()误用?
- Yield是一个静态的原生(native)方法
- Yield告诉当前正在执行的线程把运行机会交给线程池中拥有相同优先级的线程。
- Yield不能保证使得当前正在运行的线程迅速转换到可运行的状态
- 它仅能使一个线程从运行状态转到可运行状态,而不是等待或阻塞状态
总结:
Thread.yield()
应该做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会,从而公平竞争。因此,使用yield()
的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()
达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。
线程优先级Priority参数靠谱吗?
一点都不靠谱,建议不要用了,忘了他。虽然线程优先级就是决定线程需要多或者少分配一些处理器资源的线程属性,但是priority的实现太过于依赖具体操作系统。因此线程优先级不能作为程序正确性的依赖!
Daemon线程会导致finally不能执行?
当一个Java虚拟机中不存在非Daemon线程的时候,Java虚拟机将会退出,即所有线程都要立即停止,包括Daemon线程(守护线程)。在构建Daemon线程时,不能依靠
finally
块中的内容来确保执行关闭或者清理资源的逻辑。另外Daemon属性需要在启动线程之前设置,不能启动线程之后设置。
线程中断状态判断?
- 从java的api中可以看到,许多声明抛出
InterruptException
的方法,例如Thread.sleep(long mills)
这些方法在抛出InterruptException
之前,Java虚拟机会先将该线程的中断状态标示位清除,然后跑出InterruptException
,此时调用isInterrupted()
方法将会返回false
.如果没有抛出异常,直接调用Interrupt()
,标示位重为中断状态。- 另外
Thread.interrupted()
也会对当前线程的中断标识就行复位,虽然他是判断当前线程是否为中断状态。- 中断检测函数区别
public boolean isInterrupted() {
return isInterrupted(false);
}
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
使用模板设计模式实现独占锁同步组件
package com.genge.multithread;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
/**
* Created by Genge on 2016-06-08.
* 独占锁同步组件实现
*/
public class Mutex implements Lock {
// 推荐使用静态内部类 继承 队列同步器
private static class Sync extends AbstractQueuedSynchronizer{
protected Sync() {
super();
}
@Override
protected boolean tryAcquire(int arg) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
@Override
protected boolean tryRelease(int arg) {
if (getState() == 0) {
throw new IllegalMonitorStateException();
}
setState(0);
return true;
}
@Override
protected int tryAcquireShared(int arg) {
return super.tryAcquireShared(arg);
}
@Override
protected boolean tryReleaseShared(int arg) {
return super.tryReleaseShared(arg);
}
//是否处在独占状态
@Override
protected boolean isHeldExclusively() {
return getState() == 1;
}
@Override
public String toString() {
return super.toString();
}
Condition newCondition(){
return new ConditionObject();
}
}
private final Sync sync = new Sync();
public void lock() {
sync.acquire(1);
}
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
public boolean tryLock() {
return sync.tryAcquire(1);
}
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(time));
}
public void unlock() {
sync.release(1);
}
public Condition newCondition() {
return sync.newCondition();
}
}
AQS队列同步器独占式同步状态获取与释放过程?
在获取同步状态时,同步器维护一个同步队列,回去状态失败线程都会加入到队列中并在队列中进行自旋;移出队列(或者停止自旋)的条件是前驱节点为头节点且成功获取了同步状态。在释放同步状态时,同步器调用
tryRelease(int arg)
方法释放同步状态,然后唤醒头节点的后继结点。另外共享式与独占式最主要的区别在于同一时刻能否有多个线程同时获取到这个同步状态。