Daemon Thread
Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程,后台一些系统性的服务,比如垃圾回收线程、JIT线程) 。
如果 User Thread已经全部退出运行了,只剩下Daemon Thread存在了,那么虚拟机也就退出了(不管Daemon Thread是否结束)。
设置守护线程:
Thread daemonTread = new Thread();
daemonThread.setDaemon(true); //必须在thread.start()之前设置,否则会跑出一个IllegalThreadStateException异常。
daemonThread.isDaemon(); //检验守护线程。
在Daemon线程中产生的新线程也是Daemon的。
线程状态
Thread内部枚举类:
public enum State {
NEW, //还未start()
RUNNABLE, //(可运行状态、运行状态。到底是哪个状态由CPU时间片轮转来决定,轮到了就是运行状态,没轮到就是可运行状态。)
BLOCKED, //阻塞状态。申请某些锁或某个对象的监视器,线程会被阻塞住。
WAITING, //无限期等待状态。调用了wait方法。进入Waiting状态的线程会等待其他线程给它notify,通知到之后由Waiting状态又切换到Runnable状态继续执行。
TIMED_WAITING, //有限期等待状态。等待xx秒还是没有被notify,则自动切换到Runnable状态。
TERMINATED; //结束状态。
}
注:在实例化线程并start()之后,线程是进入可运行状态。
API
线程优先级:
并不一定是高优先级一定先完成。只是高优先级完成的概率比较大,但是低优先级还是有可能先完成的。
Thread.yield()
Thread.yield()只是对CPU的一个暗示,暗示当前线程可让出运行位置(从运行状态转到可运行状态),让其他线程占用CPU核心。注意,这只是一个hint,可能无实质影响。也就是说不能保证当前运行的线程立即转化到可运行状态。
Thread.join()
Thread t = new Thread(() -> {
//do something
});
t.start();
t.join(1000); //等待线程t结束或1000毫秒
join本质是Object.wait(long timeout),即当前线程(主线程)进入waiting状态,监控对象为t。当一个线程运行完成终止后,将会调用notifyAll方法去唤醒等待在该线程实例上的所有线程,该操作由JVM完成。
Object.wait(long timeout)
将当前线程进入waiting状态(释放了锁),直到调用Object.notify()或Object.notifyAll() 或时间超过timeout。
synchronized (MonitorObject) {
// do something
MonitorObject.wait();
// do something
MonitorObject.notifyAll();
}
wait、notify、notifyAll方法必须在同步块中(正在监视对象)。
sleep和wait主要区别:
sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
Object.notify()
Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened.
notifyAll()就是唤醒所有线程。
线程中断
public void Thread.interrupt() // 中断线程
public boolean Thread.isInterrupted() // 判断是否被中断
public static boolean Thread.interrupted() // 判断是否被中断,并清除当前中断状态
Java的中断是一种协作机制。也就是说Thread.interrupt()并不一定就中断了正在运行的线程,它只是要求线程自己在合适的时机中断自己。
interrupt()仅仅只是将线程的中断状态置为true,该中断状态由native方法interrupt0()设置。
interrupt()只针对3种情况:
If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.
If this thread is blocked in an I/O operation upon a java.nio.channels.InterruptibleChannel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a java.nio.channels.ClosedByInterruptException.
If this thread is blocked in a java.nio.channels.Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's wakeup method were invoked.
对于其他情况,只会将线程中断状态置为true。
对于非阻塞线程,只是改变了中断状态,并不会使线程停止:
Thread nonBlocking = new Thread(() -> {
while (true) {
System.out.println("Produce -> ");// do something
}
});
nonBlocking.start();
nonBlocking.interrupt();// this thread's interrupt status will be set
nonBlocking.join();
你应该这样做:
Thread nonBlocking = new Thread(() -> {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("Interrupted!");
break;
}
System.out.println("Produce -> "); /* do something */
}
});
//
nonBlocking.start();
Thread.sleep(10); //确保第一次循环跑过if判断
nonBlocking.interrupt();
nonBlocking.join();
对于阻塞线程:
Thread blocking = new Thread(() -> {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("Interrupted!");
break;
}
try {
Thread.sleep(60_000);
}
catch (InterruptedException e) {
System.out.println("InterruptedException When blocking");
/*因为抛出异常后会清除中断状态,所以设置中断状态,从而使得下一个while循环if判断为true,跳出循环。*/
Thread.currentThread().interrupt();
}
}
});
//
blocking.start();
Thread.sleep(10); //确保第一次循环跑过if判断
blocking.interrupt();
blocking.join();
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。