线程的三种启动方式
- X extends Thread ;然后X.run
2.X implements Runnable; 然后有Thread 来运行
3.X implements Callable; 然后有Thread 来运行
第一种继承子Thread 类
public class ThreadExtends extends Thread{
@Override
public void run() {
super.run();
System.out.println("测试数据");
}
}
启动方式:
ThreadExtends threadExtends = new ThreadExtends();
threadExtends.start();
第二种方式
实现Runnable
接口
public class ThreadRunnable implements Runnable {
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println("测试Runnable currentThread"+name);
}
}
启动方式:
new Thread(new ThreadRunnable()).start();
第三种 实现Callable<V>
接口,这种方式带有返回值的
import java.util.concurrent.Callable;
public class ThreadCall implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("callable =======");
return "测试";
}
}
启动方式:
ThreadCall call = new ThreadCall();
FutureTask<String> futureTask = new FutureTask<>(call);
new Thread(futureTask).start();
String s = futureTask.get();
System.out.println(s);
输出:
实现Callable 接口的结果展示
以上三种方式,第 1,2 中方式运行完成以后无法获取运行的结果, 从JDK1.5 开始就提供了Callable
和Future
,通过他们可以获取线程运行完成后的结果.
Callabel
只是声明了一个接口,有个call()
的方法,只是一个泛型接口,call()
函数返回的类型就是传进来的类型.
//只是一个接口
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
Future
就是对具体的Runnable
和Callable
任务的执行结果进行取消、查询和是否完成、获取结果。
必要时用get()
方法获取执行结果,但是该方法会阻塞到任务结束返回结果。
因为Future
是一个接口,无法直接用来从创建对象的,因此就有了FutureTask
。
public class FutureTask<V> implements RunnableFuture<V>
package java.util.concurrent;
/**
* A {@link Future} that is {@link Runnable}. Successful execution of
* the {@code run} method causes completion of the {@code Future}
* and allows access to its results.
* @see FutureTask
* @see Executor
* @since 1.6
* @author Doug Lea
* @param <V> The result type returned by this Future's {@code get} method
*/
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}
FutureTask
实现了RunnableFuture
接口,RunnableFuture
接口集成了Runnable
接口和Future
接口,所以它皆可以作为Runnable
被线程执行,有可以作为Future
得到Callable
得到返回值。事实上FutureTask
是Future
的唯一实现类。要new 一个FutureTask 有两个方法:
中止
- 线程自然中止:要么是run 执行完毕了,要么就是出现异常被迫停止了。
- 手动中止:已经被废弃的方式就不提了,现在基本不用了。被废弃原因是会造成死锁,程序运行在不稳定状态下。
- 安全中止:则是其他线程调用当前线程的
interrupt()
方法对其进行一个中断操作,线程则通过isInterrupt()
来判断是否中止,也可以调用Thread.isInterrupt()
来判断当前线程是否被中止。
不提倡用自定义的标记来进行中断
因为线程运行是不规则的,你需要断开的,但是没有断开,这时候程序就会出现运行问题。
网友评论