一、线程的启动
-
extends Thread
-
implements Runnable
-
implements Callable
public class newThread {
//1、继承Thread类
private static class ExtendsThread extends Thread {
public void run(){
System.out.println("I am extends Thread");
}
}
//2、implements Runnable
private static class UseRunnable implements Runnable {
@Override
public void run() {
System.out.println("I am implements Runnable");
}
}
//3、implements Callable
private static class UseCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("I am implements Callable");
return "Callable Return";
}
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExtendsThread t1 = new ExtendsThread();
t1.start();
UseRunnable useRunnable = new UseRunnable();
Thread t2 = new Thread(useRunnable);
t2.start();
//启动Callable接口的实现类,需通过FutureTask来启动线程
UseCallable useCallable = new UseCallable();
FutureTask<String> futureTask = new FutureTask<String>(useCallable);
futureTask.run();
System.out.println(futureTask.get());
}
}
运行上述代码后的效果
二、线程的中断
停止一个线程意味着在任务处理完任务之前停掉正在做的操作,也就是放弃当前的操作。
Q:怎么样才能让Java里的线程安全停止工作呢?
1)线程自然终止:
自然执行完或抛出未处理异常
2)stop()、resume()、suspend()已不建议使用
stop():导致线程不正确释放资源
suspend():容易导致死锁
3)interrupt():
它并不会直接终止掉一个正在运行的进程,而是在当前线程中,打一个需要『被停止』的标签,而是否停止应该由当前线程自己决定,所以这也决定了我们需要在编写Thread或者Runnable代码的时候,有更高的要求,要明确自己如何被安全的停止。
既然interrupt()只是为我们对当前线程做了一个简单的停止标记,而JDK同时也为我们提供了获取这个标记值的API。
- Thread.interrupted():检查当前运行这段代码的线程,是否已经被停止。
- this.isInterrupted():检查当前this指定的线程,是否已经被停止。
如下代码所示:
public class UseInterrupt extends Thread{
public UseInterrupt(String threadName) {
super(threadName);
}
public void run() {
String threadName = Thread.currentThread().getName();
while(!isInterrupted()) {
System.out.println(threadName + " is running!");
}
System.out.println(threadName + " interrupt flag is "+ isInterrupted());
}
public static void main(String[] args) throws InterruptedException {
UseInterrupt t = new UseInterrupt("interruptThread");
t.start();
Thread.sleep(50);
t.interrupt();
}
}
这段代码会停止线程,但是如果将while里的判断条件,改为true,则线程将永远不会停止
public class UseInterrupt extends Thread{
public UseInterrupt(String threadName) {
super(threadName);
}
public void run() {
String threadName = Thread.currentThread().getName();
while(true) {
System.out.println(threadName + " is running!");
}
}
public static void main(String[] args) throws InterruptedException {
UseInterrupt t = new UseInterrupt("interruptThread");
t.start();
Thread.sleep(50);
t.interrupt();
}
}
4)isInterrupted():
判断当前线程是否处于中断状态
查看isInterrupted()源码可知,isInterrupted()是Thread类提供的方法。
>>> 所以,只有继承Thread类的线程类,才可直接调用isInterrupted()方法判断中断标志位是否为true
4.1) 继承Thread类实现的线程,使用isInterrupted()判断
public class UseInterrupt extends Thread{
public UseInterrupt(String threadName) {
super(threadName);
}
public void run() {
String threadName = Thread.currentThread().getName();
while(!isInterrupted()) {
System.out.println(threadName + " is running!");
}
System.out.println(threadName + " interrupt flag is "+ isInterrupted());
}
public static void main(String[] args) throws InterruptedException {
UseInterrupt t = new UseInterrupt("interruptThread");
t.start();
Thread.sleep(50);
t.interrupt();
}
}
运行上述代码后的效果:
4.2)implements Runnable类实现的线程,使用isInterrupted()判断
public class RunnableUseInterrupt implements Runnable{
@Override
public void run() {
String threadName = Thread.currentThread().getName();
while(!Thread.currentThread().isInterrupted()) {
System.out.println(threadName+" is running!");
}
System.out.println(threadName+" interrupt flag is "+Thread.currentThread().isInterrupted());
}
public static void main(String[] args) throws InterruptedException {
RunnableUseInterrupt run = new RunnableUseInterrupt();
Thread t = new Thread(run, "runnableUseInterrupt");
t.start();
Thread.sleep(20);
t.interrupt();
}
}
运行上述代码的效果
5)方法里如果抛出InterruptedException,线程的中断标志位会被复位成false。
public class HasInterruptException {
private static class UseThread extends Thread {
public UseThread(String name) {
super(name);
}
public void run() {
String threadName = Thread.currentThread().getName();
while(!isInterrupted()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println(threadName+" interrupt flag is "+isInterrupted());
e.printStackTrace();
}
}
System.out.println(threadName+" interrupt flag is "+isInterrupted());
}
}
public static void main(String[] args) throws InterruptedException {
Thread endThread = new UseThread("HasInterruptEx");
endThread.start();
Thread.sleep(500);
endThread.interrupt();
}
}
此段代码运行后,线程永远不会被退出,即使调用了interrupt()方法,也不会停止线程。
如果确实是需要中断线程,要求我们自己在catch语句块里再次调用interrupt()
public class HasInterruptException {
private static class UseThread extends Thread {
public UseThread(String name) {
super(name);
}
public void run() {
String threadName = Thread.currentThread().getName();
while(!isInterrupted()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println(threadName+" interrupt flag is "+isInterrupted());
e.printStackTrace();
interrupt();
}
}
System.out.println(threadName+" interrupt flag is "+isInterrupted());
}
}
public static void main(String[] args) throws InterruptedException {
Thread endThread = new UseThread("HasInterruptEx");
endThread.start();
Thread.sleep(500);
endThread.interrupt();
}
}