Java线程相关方法
1. sleep
public static native void sleep(long millis) throws InterruptedException
当millis小于0的时候抛出IllegalArgumentException
,当该线程被中断时,抛出InterruptedException
public static void sleep(long millis, int nanos) throws InterruptedException
当millis小于0,或者nanos不在0 ~ 999999范围内的时候抛出IllegalArgumentException
,当该线程被中断时,抛出InterruptedException
。
该方法使当前线程暂时停止运行,但是它并不释放对象锁。也就是说如果有synchronized
同步方法,或同步块,其它线程仍然不能访问加锁的代码。
public class Main {
public static void main(String[] args) {
Thread t = new Thread(new FiveSecondSleepRunnable());
t.start();
//t.interrupt();
}
private static class FiveSecondSleepRunnable implements Runnable{
@Override
public void run() {
try {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
Thread.sleep(5000);
stopWatch.stop();
System.out.println("Sleep " + stopWatch.getTime() + " millisecond");
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("I am interrupted");
}
}
}
}
结果如下:当线程t被其它线程中断时, 即注释的代码t.interrupt();
启用时,会抛出异常,结果如下:
2.join
public final synchronized void join(long millis) throws InterruptedException
public final synchronized void join(long millis, int nanos) throw InterruptedException
public final void join() throws InterruptedException
当一个线程调用join方法,其它线程要等待该线程到时间结束,或者到该线程生命结束。
public class Example {
public static void main(String[] args) {
Thread t1 = new Thread(new MyRunnable(), "t1");
Thread t2 = new Thread(new MyRunnable(), "t2");
Thread t3 = new Thread(new MyRunnable(), "t3");
t1.start();
//start second thread after waiting for 2 seconds or if it's dead
try {
t1.join(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
//start third thread only when first thread is dead
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
t3.start();
//let all threads finish execution before finishing main thread
try {
t1.join();
t2.join();
t3.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("All threads are dead, exiting main thread");
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("Thread started:::"+Thread.currentThread().getName());
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread ended:::"+Thread.currentThread().getName());
}
}
如上代码,t2线程要等待t1线程执行2000毫秒后才会执行,t3线程要等到t1线程执行结束才能执行。主线程要等到t1,t2,t3线程都结束时才会打印出All threads are dead, exiting main thread
。结果如下
3.yield
public static native void yield()
该方法暗示调度器,线程自己放弃当前对处理器的使用权,但是这只是一个暗示,调度器可以忽视。yield和sleep的区别在于,sleep不管线程池中是否有可运行状态的线程,都会使线程进入TIMED_WAITING状态并且至少会等待超时时间到达后才会再次执行。而yield则是线程放弃自己对处理器的使用权,进入RUNNABLE状态,若此时没有线程使用处理器,那么它又会进入RUNNING状态。
4.interrupt
public void interrupt()
该方法并不是真正地去中断目标线程,而是设置目标线程的中断状态/标志,至于如何去响应这个中断,则是由编程人员来决定。
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 an InterruptibleChannel then the channel will be closed, the thread’s interrupt status will be set, and the thread will receive a ClosedByInterruptException.
If this thread is blocked in a 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.
If none of the previous conditions hold then this thread’s interrupt status will be set.
前三种情形其实是描述了如果线程处于等待状态或是阻塞在某一种资源上,那么 interrupt() 方法会使得线程跳出这种状态继续执行下去。第四种情形则描述了如果线程正在正常执行,那么 interrupt() 的效果则是设置了线程的中断状态,至于怎么处理这种状态,可以选择忽略也可以按需处理。
某些API有中断处理,如
- Object.wait()/Thread.sleep()
- 大部分
java.util.concurrent
包里的类 - Java NIO,但是不是使用
InterruptedException
,而是使用ClosedByInterruptException
对于这些Api,我们可以在try-catch中对中断做出处理,如
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread thread = new MyThread();
thread.start();
TimeUnit.SECONDS.sleep(5);
thread.interrupt();
}
}
class MyThread extends Thread {
public void run() {
System.out.println("Sleeppppppppppp");
try {
TimeUnit.SECONDS.sleep(100);
System.out.println("Awakeeeeeeeee");
} catch (InterruptedException e) {
System.out.println("I am interrupted");
}
}
}
MyThread线程sleep 100秒,主线程在运行5秒之后中断MyThread。在try-catch块中,我们进入处理,输入I am interrupted
。结果如图,首先输出Sleeppppppppppp
,但是并没有来得及输出Awakeeeeeeeee
就中断了。
而对于没有中断处理的情况,就需要我们自己判断线程中断状态,作出相应处理。如下,修改MyThread类,main函数不变。我们在while循环中做业务处理,但是因为是无线循环,我们需要判断中断状态,如果线程被中断,我们就跳出循环。
class MyThread extends Thread {
public void run() {
while (true) {
// Do what you what-does-java-lang-thread-interrupt-do
// ...
if (Thread.currentThread().isInterrupted()) {
System.out.println("I am interrupted");
break;
}
}
System.out.println("Thread exit");
}
}
结果如下图,通过判断线程中断状态来结束线程。