通过继承Thread并且重写其run(),run方法中即线程执行任务。创建后的子类通过调用 start() 方法即可执行线程方法。
继承Thread 方法创建的线程之间是并行的,线程之间不能共享线程类的实例变量
/**
* 通过继承Thread实现线程
*/
public class ThreadTest extends Thread{
@Override
public void run() {
//todo somethings
}
public static void main(String[] args) {
new ThreadTest().start() ;
}
}
实现Runnable
实现Runnable接口,并重 run() 方法,此run方法是线程执行体。接着创建 Runnable实现类的对象,作为创建Thread对象的参数target,此Thread对象才是真正的线程对象。通过实现Runnable接口的线程类,是互相共享资源的sheng
/**
* 通过实现Runnable接口实现的线程类
*/
public class RunnableTest implements Runnable {
private int i ;
@Override
public void run() {
//todo
}
public static void main(String[] args) {
RunnableTest runnableTest = new RunnableTest() ;
new Thread(runnableTest,"线程1").start() ;
}
}
使用Callable和Future创建线程
在java1.5 之后提供了 Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果Callable接口代表一段可以调用并返回结果的代码;Future接口表示异步任务,是还没有完成的任务给出的未来结果。所以说Callable用于产生结果,Future用于获取结果
/**
* 使用Callable+Future获取执行结果
**/
public class CallableFutureTest {
public static void main(String[] args) {
//创建线程池
ExecutorService es = Executors.newSingleThreadExecutor();
//创建Callable对象任务
CallableDemo calTask = new CallableDemo();
//提交任务并获取执行结果
Future future = es.submit(calTask);
//关闭线程池
es.shutdown();
try {
Thread.sleep(2000);
System.out.println("主线程在执行其他任务");
if (future.get() != null) {
//输出获取到的结果
System.out.println("future.get()-->" + future.get());
} else {
//输出获取到的结果
System.out.println("future.get()未获取到结果");
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("主线程在执行完成");
}
}
class CallableDemo implements Callable {
private int sum;
@Override
public Integer call() throws Exception {
System.out.println("Callable子线程开始计算啦!");
Thread.sleep(2000);
for (int i = 0; i < 100; i++) {
sum = sum + i;
}
System.out.println("Callable子线程计算结束!");
return sum;
}
}
//执行结果
Callable子线程开始计算啦!
Callable子线程计算结束!
主线程在执行其他任务
future.get()-->4950
主线程在执行完成
//Callable+FutureTask
public class CallableFutureTest {
public static void main(String[] args) {
//创建线程池
ExecutorService es = Executors.newSingleThreadExecutor();
//创建Callable对象任务
CallableDemo calTask = new CallableDemo();
//创建FutureTask
FutureTask futureTask = new FutureTask<>(calTask);
//执行任务
es.submit(futureTask);
//关闭线程池
es.shutdown();
try {
Thread.sleep(2000);
System.out.println("主线程在执行其他任务");
if (futureTask.get() != null) {
//输出获取到的结果
System.out.println("futureTask.get()-->" + futureTask.get());
} else {
//输出获取到的结果
System.out.println("futureTask.get()未获取到结果");
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("主线程在执行完成");
}
}
class CallableDemo implements Callable {
private int sum;
@Override
public Integer call() throws Exception {
System.out.println("Callable子线程开始计算啦!");
Thread.sleep(2000);
for (int i = 0; i < 100; i++) {
sum = sum + i;
}
System.out.println("Callable子线程计算结束!");
return sum;
}
}
FutureTask类实现了RunnableFuture接口 而RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值
作者:香沙小熊
链接:https://www.jianshu.com/p/ccb118a16f05
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
线程的启动 可以用 .start() 和.start() 两种方式,两种方式都能启动线程,区别在于 .start() 启动线程多个线程之间是并行进行,而 .run()线程之间是顺序执行
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)