JavaSE---线程控制
/** * * 当线程在系统内运行时,程序无法 准确控制 线程的轮换执行,可以通过 一些机制 保证线程的协调运行; * * 实现机制: * 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; } }