/**
*
* 当线程在系统内运行时,程序无法 准确控制 线程的轮换执行,可以通过 一些机制 保证线程的协调运行;
*
* 实现机制:
* 1、Object的wait(), notify(), notifyAll() ,必须 由 同步监视器 调用;
* 适用 synchronized 情形;
*
* wait:
* 导致 当前线程等待,直到 其他线程 调用 该同步监视器的notify、notifyAll 唤醒 该线程;
*
* 调用wait方法,当前线程 会释放 对 该同步监视器的锁定;
*
* wait三种形式:
* wait():
* 当前线程 无时间限制,直到 其他线程 通知;
* wait(long timeout):
* wait(long timeout, int nanos):
* 带毫秒(或 带毫秒+微妙);
* 当前线程 等待 指定时间后 自动苏醒;
*
* notify:
* 唤醒 在此同步监视器 上等待的单个线程;
* 如果 此同步监视器 有多个线程 等待,则会随机唤醒其中一个;
*
* 只有 当前线程 放弃 对该同步监视器的锁定后,才能执行被唤醒的线程;
*
* notifyAll:
* 唤醒 在此同步监视器 上等待的所有线程;
*
* 只有 当前线程 放弃 对该同步监视器的锁定后,才能执行被唤醒的线程;
*
* 2、JDK提供的 Condition,由 指定Lock实例关联的Condition实例 调用;
* 适用 JDK的 Lock情形;
*
* Condition将 同步监视器方法(wait、notify、notifyAll) 分解成 截然不同的对象;
* 将 Condition对象 与 Lock对象 组合使用;
* Condition对象 实质上 被绑定到 一个Lock实例上,要获取指定Lock实例的Condition实例,调用Lock.newCondition();
*
* await():
* 导致 当前线程 等待,直到其他线程 调用 该Condition实例的signal 或 signalAll 唤醒 该线程;
*
* Condition实例 对应的Lock实例 自动释放;
*
* signal():
* 唤醒 在此Lock实例 上 等待的单个线程;
* 如果 此Lock实例有多个重新,则随机唤醒其中一个线程;
*
* 只有 当前线程 释放 对该Lock实例的锁定后,才可以执行 被唤醒的线程;
*
* signalAll();
* 唤醒 在此Lock实例 上 所有等待的线程;
*
* 只有 当前线程 释放 对该Lock实例的锁定后,才可以执行 被唤醒的线程;
*
*/
public static void main(String[] args) throws InterruptedException {
Thread.currentThread().setName("mainThread");
// joinTest();
// sleepTest();
// yieldTest();
// threadPriorityTest();
// threadGroupTest();
exceptionHandlerTest();
// threadLoaclTest();
}
private static void threadLoaclTest() {
// ThreadLocal
}
private static void exceptionHandlerTest() {
Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler());
SubThread subThread = new SubThread();
subThread.setName("SubThread");
subThread.start();
}
static class MyExceptionHandler implements Thread.UncaughtExceptionHandler{
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("MyExceptionHandler uncaughtException... ");
System.out.println("currentThread:"+ t.getName());
System.out.println("e:"+ e);
}
}
/**
* 每个Java线程都是 某个线程组 的成员;
*
* 线程组 提供一种机制,使得多个线程 集于 一个对象内,对 它们进行整体操作;
*
* 线程只能属于一个线程组,并且当线程产生后不能改变它所属的线程组,直到 该线程死亡;
*
* 默认情况下,子线程与创建它的父线程 处于同一个 线程组内;
*
* 【线程组内的线程异常处理】
* JDK5开始,Java增强了 线程的异常处理,如果线程执行过程中出现 异常,
* JVM会在结束该线程之前 查找 是否有对应的java.lang.Thread.UncaughtExceptionHandler对象,
* 如果找到,调用java.lang.Thread.UncaughtExceptionHandler对象的uncaughtException处理异常;
*
* java.lang.Thread.UncaughtExceptionHandler
* Thread类的一个内部公共静态接口;
* {
* // t:出现异常的线程,e:该线程抛出的异常
* void uncaughtException(Thread t, Throwable e);
* }
*
* 异常处理器设置:
* public class Thread implements Runnable{
*
* public interface UncaughtExceptionHandler {
* void uncaughtException(Thread t, Throwable e);
* }
*
* private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
* private ThreadGroup group;
*
* public UncaughtExceptionHandler getUncaughtExceptionHandler() {
* return uncaughtExceptionHandler != null ? uncaughtExceptionHandler : group;
* }
*
* // Dispatch an uncaught exception to the handler. 转发uncaught exception;
* // This method is intended to be called only by the JVM. 由JVM调用;
* private void dispatchUncaughtException(Throwable e) {
* getUncaughtExceptionHandler().uncaughtException(this, e);
* }
*
* // 为该线程类的 所有线程实例 设置 默认的异常处理器;
* public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {}
*
* // 为指定线程实例 设置 异常处理器
* public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {}
*
* }
*
*
* ThreadGroup实现了java.lang.Thread.UncaughtExceptionHandler,所以 每个线程所属的线程组 将会作为默认的异常处理器;
* public class ThreadGroup implements Thread.UncaughtExceptionHandler{
* public void uncaughtException(Thread t, Throwable e) {
* Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler();
* }
* }
*
*/
private static void threadGroupTest() {
System.out.println(Thread.currentThread().getName() + " ThreadGroup: " + Thread.currentThread().getThreadGroup().getName());
SubThread subThread = new SubThread();
subThread.setName("SubThread");
subThread.start();
/**
* mainThread ThreadGroup: main
* SubThread Priority : 5
* SubThread---running
* SubThread---running
* SubThread---running
* SubThread ThreadGroup: main
*/
}
/**
* 每个线程 默认的优先级 :
* 与 创建它的父线程 具有相同的优先级;
*
* 线程优先级范围 1 到 10;
*
* Java采用的是一种简单、固定的调度法,即固定优先级调度;
*/
private static void threadPriorityTest() {
System.out.println(Thread.currentThread().getName() + " Priority : " + Thread.currentThread().getPriority());
SubThread subThread = new SubThread();
subThread.start();
/**
* mainThread Priority : 5
* Thread-0 Priority : 5
*/
}
/**
* yield :
* 让当前执行的线程暂停,但 不进入阻塞状态,直接进入就绪状态;
*
* yield只是 让当前执行线程暂停一下,让系统的线程调度器重新调度;
*
* 当 某个线程调用了yield后,只有 优先级与当前线程相同(或 优先级高于当前线程的就绪状态的线程) 才会获得执行机会;
*/
private static void yieldTest() {
Thread.yield();
}
/**
* sleep:
* sleep 将当前执行的线程 进入阻塞状态,直到 过了 阻塞时间 才会进入 就绪状态;
* 其他线程将会抢CPU资源,不关心 线程优先级;
*
*/
private static void sleepTest() throws InterruptedException {
for (int i = 0; i < 4; i ++){
if (i == 3){
Thread.sleep(5000);
}
System.out.println(Thread.currentThread().getName() + ": i=" +i);
}
}
/**
* join:
* 当前执行线程 调用 其他线程的join方法,当前线程 进入阻塞状态,直到 其他线程执行完成;
*/
static void joinTest() throws InterruptedException {
SubThread subThread = new SubThread();
subThread.setName("SubThread");
//join
for (int i = 0; i < 5; i++){
System.out.println(Thread.currentThread().getName() + "---running");
if (i == 3){
subThread.start();
System.out.println(subThread.getName() + "---join");
subThread.join();
}
}
/**
* mainThread---running
* mainThread---running
* mainThread---running
* mainThread---running
* SubThread---join
* SubThread Priority : 5
* SubThread---running
* SubThread---running
* SubThread---running
* mainThread---running
*/
}
static class SubThread extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " Priority : " + Thread.currentThread().getPriority());
for (int i = 0; i< 3; i++){
System.out.println(this.getName() + "---running");
}
System.out.println(Thread.currentThread().getName() + " ThreadGroup: " + Thread.currentThread().getThreadGroup().getName());
int i = 1/0;
}
}