Java创建并执⾏线程的四种⽅法
java⾥⾯创建线程有四种⽅式:
⽆返回:
1. 实现Runnable接⼝,重写run();
2. 继承Thread类,重写run();
有返回:
1. 实现Callable接⼝,重写call(),利⽤FutureTask包装Callable,并作为task传⼊Thread构造函数;
2. 利⽤线程池;
下⾯来看看具体的创建⽅式:
1. 继承Thread类,重写run();
创建:创建线程只需要继承Thread类,然后在run⽅法⾥写下线程要实现的任务即可;
调⽤:通过调⽤start⽅法来启动线程⽽不能直接调⽤run⽅法。
① Thread类本质上是实现了Runnable接⼝,Thread对象代表⼀个线程的实例。
② Runnable接⼝只有⼀个抽象的run()⽅法。
③ 启动线程的唯⼀⽅法就是通过Thread类的start()实例⽅法。
④ start()⽅法是⼀个native⽅法,它将启动⼀个新线程,并执⾏run()⽅法。
⑤ ⾃定义类直接extend Thread,并复写run()⽅法,就可以启动新线程并执⾏⾃⼰定义的run()⽅法。
2. 创建任务,实现Runnable接⼝,重写run()。(受欢迎)
因为Java只能单继承,继承了Thread类就不能再继承别的类了所以实现继承更推崇的是让线程类实现Runnable接⼝。
将Runnbale作为参数传⼊Thread的构造函数,创建Thread.
3. Callable接⼝只包含抽象⽅法V call()。
利⽤Callable接⼝创建并启动新线程的步骤:
① 定义MyClass实现Callable接⼝;Class MyClass implements Callable
② 重写call(),将执⾏的代码写⼊;
③ 创建FutureTask的对象;FutureTask中定义了run(),run()内部调⽤了call(),并保存了call()的返回值;FutureTask futuretask = new FutureTask(newMyClass());
④ 创建Thread的对象;Thread thread = new Thread(futuretask);//传⼊参数Runnable接⼝
⑤ 启动线程;thread.start();[图⽚]
⑥ 可通过FutureTask类的get()⽅法获得线程执⾏结束后的返回值,即call的返回值。();
import urrent.Callable;
import urrent.ExecutionException;
import urrent.FutureTask;
public class MyThread {
public static void main(String[] args) throws InterruptedException {
FutureTask<Integer> task = new FutureTask<Integer>(new CallableImpl());
Thread thread = new Thread(task);
thread.start();
try {
System.out.println("() returns " + ());
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class CallableImpl implements Callable<Integer> {
private static Integer value = 0;
@Override
public Integer call() throws Exception {
System.out.println("执⾏call⽅法之前 value = " + value);
value = value.intValue() + 1;
System.out.println("执⾏call⽅法之后 value = " + value);
return value;
}
}
运⾏结果:
执⾏call⽅法之前 value = 0
执⾏call⽅法之后 value = 1
<() returns 1
4. 通过线程池来创建线程
① new ThreadPoolExecutor(…);
② 创建任务Task implements Callable,重写run()⽅法;
③ 通过线程池的execute()或submit()将任务command传⼊线程池;
④ 获取返回值:
1) 实现Callable接⼝,重写call()⽅法
class CallableImpl implements Callable
2) 定义线程池
ThreadPoolExecutor executor
3) 利⽤submit()⽅法提交任务
Future<?> future = executor.submit(new CallableImpl());
java线程池创建的四种
5) 利⽤FutureTask类get()⽅法获取返回值
res = ();
这⾥future申明为Future对象,但是它是由FutureTask实现的,也可以直接申明为FutureTask future:
import urrent.ArrayBlockingQueue;
import urrent.ExecutionException;
import urrent.FutureTask;
import urrent.ThreadPoolExecutor;
import urrent.TimeUnit;
public class MyThreadPool {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(20));
Future task;
for (int i = 0; i < 5; i++) {
task = executor.submit(new CallableImpl());
System.out.println("线程返回结果:" + ());
}
executor.shutdown();
}
}
class RunnableImpl implements Runnable {
@Override
public void run() {
/
/ TODO Auto-generated method stub
System.out.println("hhh");
System.out.println(Thread.currentThread().getName());
}
}
运⾏结果:
执⾏call⽅法之前 value = 0
执⾏call⽅法之后 value = 1
线程返回结果:1
执⾏call⽅法之前 value = 1
执⾏call⽅法之后 value = 2
线程返回结果:2
执⾏call⽅法之前 value = 2
执⾏call⽅法之后 value = 3
线程返回结果:3
执⾏call⽅法之前 value = 3
执⾏call⽅法之后 value = 4
线程返回结果:4
执⾏call⽅法之前 value = 4
执⾏call⽅法之后 value = 5
线程返回结果:5
总结:
线程的创建有四种⽅式:主要分为有返回和⽆返回,具体根据使⽤场景来选择。
1. 如果不需要返回且线程数量⼩,则建议采⽤实现Runnable接⼝,重写run()的⽅式;
2. 如果需要返回且线程数量⼩,则建议采⽤实现Callable接⼝,重写call(),利⽤FutureTask包装成⼀个Runnable,再作为参数传⼊Thread的构造⽅法的⽅式创建线程;
3. 如果线程数量较多,则建议采⽤线程池⽅式创建:execute提交任务实现⽆返回操作,submit提交任务实现有返回操作。
补充:FutureTask
JDK1.8中FutureTask实现了RunnableFuture,⽽RunnableFuture顾名思义就是Runnable接⼝和Future接⼝的结合体。因
此,FutureTask对象可以作为Runnable对象来⽤,⽐如
Thread thread = new Thread(new FutureTask<V>());
也可以作为Future来⽤。这就是Java的有魅⼒的地⽅。。。
public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
Callable、Future、Runnable、FutureTask的联系与区别见下⼀篇博⽂。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。