Thread
构造方法
Thread 类提供六种构造方法,内部都是调用了下面的私有方法
private void init(ThreadGroup g, Runnable target, String name,long stackSize)
由方法参数可见我们可以通过构造函数指定的线程属性是
- 线程组:线程组,当参数为空时首先检查系统是否存在Security(System.getSecurityManager()),存在则使用Security的线程组,否则使用父线程所在的线程组。按照Effective Java 73条的记述不推荐使用线程组。
总而言之,线程组并没有提供太多有用的功能,而且他们提供的许多功能还都是由缺陷的,我们最好把线程组看作是一个不成功的实验,你可以忽略掉他们,就当他们不存在一样,如果你正在设计的一个类需要处理线程的逻辑组,或许就应该使用线程池executor
- 线程执行对象:Runnable对象,如果不传则应该继承Thread类并覆盖其run方法
- 线程名字:默认值是“Thread-”+n ,表示线程的名字。
- 线程私有栈大小:默认值是0,如果指定的话这个参数也是高度依赖于平台的,通常当指定一个大的值时表示该线程可以实现一个更大的递归深度(不会抛出StackOverflowError),当指定一个小的值时表示同一时间可以运行更多的线程(OutOfMemoryError).但是在一些平台,这个参数是无效的.因此使用时需要极其小心。
其他属性
- 线程优先级:setPriority 设定范围1-10
- 线程是否是守护线程:setDaemon 当不存在其他线程时守护线程将被自动终止,例如垃圾回收线程。
- 线程异常处理:setUncaughtExceptionHandler 设定默认的异常处理,getDefaultUncaughtExceptionHandler方法是thread类的静态方法用来设定所有thread的默认异常处理。
生命周期方法
- 启动:start(),导致此线程开始执行,JAVA虚拟机会调用该线程的run方法,这是会有两个线程同时执行,当前线程和运行线程run方法的线程,不要重复调用start方法,一个线程运行结束后也不要在重新启动它,也不要直接使用run方法,这样run方法仍然是在当前线程下运行。
- 休眠:sleep(long millis)/sleep(long millis, int nanos) 静态方法让当前线程休眠一段时间,精度受制于系统的计时器和调度器,休眠期间不会丢弃任何的监听器,如果线程在休眠期间被中断则会抛出InterruptedException异常
- 中断:interrupt() 当前线程可以任意中断自身,当中断其他线程时,可能会抛出SecurityException;当要被中断的线程处在被对象监控器调用wait,或者自身的join,sleep方法时,设置的中断状态会被清除,并抛出InterruptedException;当线程被一个可中断的I/O通道阻塞时,线程的中断状态会被设置,线程会接收到ClosedByInterruptException;如果线程正在java.nio.channels.Selector中被阻塞,则中断状态会被设定,线程会立即从选中操作中返回,有可能携带费0值,就像选择器的唤醒方法被调用一样。当不是以上这些状态时,中断状态被正确设定,也不会有任何副作用。
- 检查线程是否处于中断状态:静态方法interrupted和isInterrupted,其中interrupted方法被调用时会重置中断状态因此建议使用isInterrupted
- 让出:yield() 向调度器提示当前线程愿意产生其当前对处理器的使用。调度程序可以随意忽略此提示。产量是一种启发式尝试,以改善线程之间的相对进展,否则会过度利用CPU。它的使用应结合详细的剖析和基准测试,以确保它实际上具有预期的效果。使用此方法很少适合。它可能有用于调试或测试目的,它可能有助于重现由于竞争条件的错误。在设计诸如java.util.concurrent.locks包中的并发控制结构的并发控制结构时,它也可能很有用。
- 等待线程结束:join 其他线程等待当前线程执行完毕。
- 另外还有目前不再推荐使用的的暂停(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();
}
}