Thread

构造方法

Thread 类提供六种构造方法,内部都是调用了下面的私有方法

private void init(ThreadGroup g, Runnable target, String name,long stackSize)

由方法参数可见我们可以通过构造函数指定的线程属性是

  1. 线程组:线程组,当参数为空时首先检查系统是否存在Security(System.getSecurityManager()),存在则使用Security的线程组,否则使用父线程所在的线程组。按照Effective Java 73条的记述不推荐使用线程组。

总而言之,线程组并没有提供太多有用的功能,而且他们提供的许多功能还都是由缺陷的,我们最好把线程组看作是一个不成功的实验,你可以忽略掉他们,就当他们不存在一样,如果你正在设计的一个类需要处理线程的逻辑组,或许就应该使用线程池executor

  1. 线程执行对象:Runnable对象,如果不传则应该继承Thread类并覆盖其run方法
  2. 线程名字:默认值是“Thread-”+n ,表示线程的名字。
  3. 线程私有栈大小:默认值是0,如果指定的话这个参数也是高度依赖于平台的,通常当指定一个大的值时表示该线程可以实现一个更大的递归深度(不会抛出StackOverflowError),当指定一个小的值时表示同一时间可以运行更多的线程(OutOfMemoryError).但是在一些平台,这个参数是无效的.因此使用时需要极其小心。

其他属性

  1. 线程优先级:setPriority 设定范围1-10
  2. 线程是否是守护线程:setDaemon 当不存在其他线程时守护线程将被自动终止,例如垃圾回收线程。
  3. 线程异常处理:setUncaughtExceptionHandler 设定默认的异常处理,getDefaultUncaughtExceptionHandler方法是thread类的静态方法用来设定所有thread的默认异常处理。

生命周期方法

  1. 启动:start(),导致此线程开始执行,JAVA虚拟机会调用该线程的run方法,这是会有两个线程同时执行,当前线程和运行线程run方法的线程,不要重复调用start方法,一个线程运行结束后也不要在重新启动它,也不要直接使用run方法,这样run方法仍然是在当前线程下运行。
  2. 休眠:sleep(long millis)/sleep(long millis, int nanos) 静态方法让当前线程休眠一段时间,精度受制于系统的计时器和调度器,休眠期间不会丢弃任何的监听器,如果线程在休眠期间被中断则会抛出InterruptedException异常
  3. 中断:interrupt() 当前线程可以任意中断自身,当中断其他线程时,可能会抛出SecurityException;当要被中断的线程处在被对象监控器调用wait,或者自身的join,sleep方法时,设置的中断状态会被清除,并抛出InterruptedException;当线程被一个可中断的I/O通道阻塞时,线程的中断状态会被设置,线程会接收到ClosedByInterruptException;如果线程正在java.nio.channels.Selector中被阻塞,则中断状态会被设定,线程会立即从选中操作中返回,有可能携带费0值,就像选择器的唤醒方法被调用一样。当不是以上这些状态时,中断状态被正确设定,也不会有任何副作用。
  4. 检查线程是否处于中断状态:静态方法interrupted和isInterrupted,其中interrupted方法被调用时会重置中断状态因此建议使用isInterrupted
  5. 让出:yield() 向调度器提示当前线程愿意产生其当前对处理器的使用。调度程序可以随意忽略此提示。产量是一种启发式尝试,以改善线程之间的相对进展,否则会过度利用CPU。它的使用应结合详细的剖析和基准测试,以确保它实际上具有预期的效果。使用此方法很少适合。它可能有用于调试或测试目的,它可能有助于重现由于竞争条件的错误。在设计诸如java.util.concurrent.locks包中的并发控制结构的并发控制结构时,它也可能很有用。
  6. 等待线程结束:join 其他线程等待当前线程执行完毕。
  7. 另外还有目前不再推荐使用的的暂停(suspend),恢复(resume),停止(stop)方法.

如何实现线程的停止,暂停和恢复

大多数stop的使用应该被替换为代码,只需修改一些变量来指示目标线程应该停止运行。 目标线程应该定期检查这个变量,并且如果变量指示它要停止运行,则以有序的方式从其run方法返回。 为了确保停止请求的及时通信,变量必须是volatile(或者访问变量必须同步)。

原代码

private Thread blinker;

public void start() {
    blinker = new Thread(this);
    blinker.start();
}

public void stop() {
    blinker.stop();  // UNSAFE!
}

public void run() {
    while (true) {
        try {
            Thread.sleep(interval);
        } catch (InterruptedException e){
        }
        repaint();
    }
}

修改后

public class CustomerRunnable implements Runnable {
    private volatile Thread blinker;
    
    private volatile boolean threadSuspended;
    
    public void start() {
        blinker = new Thread(this);
        blinker.start();
    }
    
    public void stop() {
        System.out.println("stop thread");
        synchronized(this) {
            blinker = null;
            notify();
        }
    
    }
    
    public void suspend() {
        System.out.println("suspend thread");
        synchronized(this) {
            threadSuspended = true;
        }
    }

    public void resume() {
        System.out.println("resume thread");
        synchronized(this) {
            threadSuspended = false;
            notify();
        }
    }

    @Override
    public void run() {
        Thread currentThread = Thread.currentThread();
        while (blinker == currentThread) {
            try {
                synchronized(this) {
                    while (threadSuspended && blinker == currentThread) {
                        wait();
                    }
                }
                Thread.sleep(100);
            } catch (InterruptedException e){
            }
            repaint();
        }
    }

    private void repaint() {
        System.out.println(Thread.currentThread().getName()+ " : " +System.currentTimeMillis());
    }

    public static void main(String args[]) {
        CustomerRunnable customerRunnable = new CustomerRunnable();
        customerRunnable.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        customerRunnable.suspend();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        customerRunnable.resume();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        customerRunnable.stop();
    }
}