首页 > 编程知识 正文

java实现callable接口,callable接口是线程安全的吗

时间:2023-05-04 15:58:01 阅读:209041 作者:4470

一般遇到这种问题,第一想法去看看jdk 的api。

创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。例如,计算大于某一规定值的质数的线程可以写成:

class PrimeThread extends Thread { long minPrime; PrimeThread(long minPrime) { this.minPrime = minPrime; } public void run() { // compute primes larger than minPrime . . . } }

然后,下列代码会创建并启动一个线程:

PrimeThread p = new PrimeThread(143); p.start();

创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。采用这种风格的同一个例子如下所示:

class PrimeRun implements Runnable { long minPrime; PrimeRun(long minPrime) { this.minPrime = minPrime; } public void run() { // compute primes larger than minPrime . . . } }

然后,下列代码会创建并启动一个线程:

PrimeRun p = new PrimeRun(143); new Thread(p).start();

每个线程都有一个标识名,多个线程可以同名。如果线程创建时没有指定标识名,就会为其生成一个新名称。

二种方式,核心都是实现run方法,在run方法中实现自己的逻辑,第一个方式是通过继承来重写,实现自己的run方法,第二种方式是通过组合的方式来实现自己的run方法。题主使用的是第二种方式,SecondCreateThread 对象就是那个target,线程会去执行你的target中的run方法。

看看thread的源代码

/** * Causes this thread to begin execution; the Java Virtual Machine * calls the <code>run</code> method of this thread. * <p> * The result is that two threads are running concurrently: the * current thread (which returns from the call to the * <code>start</code> method) and the other thread (which executes its * <code>run</code> method). * <p> * It is never legal to start a thread more than once. * In particular, a thread may not be restarted once it has completed * execution. * * @exception IllegalThreadStateException if the thread was already * started. * @see #run() * @see #stop() */ public synchronized void start() { /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */ if (threadStatus != 0) throw new IllegalThreadStateException(); /* Notify the group that this thread is about to be started * so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. */ group.add(this); boolean started = false; try { start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } } private native void start0(); /** * If this thread was constructed using a separate * <code>Runnable</code> run object, then that * <code>Runnable</code> object's <code>run</code> method is called; * otherwise, this method does nothing and returns. * <p> * Subclasses of <code>Thread</code> should override this method. * * @see #start() * @see #stop() * @see #Thread(ThreadGroup, Runnable, String) */ @Override public void run() { if (target != null) { target.run(); } }

从上面的源代码中可以看到:
1、一旦调用start()方法,则会通过JVM找到run()方法去执行,怎么执行自己的逻辑代码呢?一种是继承Thread,然后重写run方法,jvm执行的就是自己的写的run方法了。一种是传入一个target,然后在Thread的run方法中调用target的run方法。

Callable接口与Runnable接口相比,还有一个很大的不同:Callable接口的实例不能作为Thread线程实例的target来使用;而Runnable接口实例可以作为Thread线程实例的target构造参数,开启一个Thread线程。

Java中的线程类型,只有一个Thread类,没有其他的类型。如果Callable实例需要异步执行,就要想办法赋值给Thread的target成员,一个Runnble类型的成员。为此,java提供了在Callable实例和Thread的target成员之间一个搭桥的类--FutureTask类。

2、如上面代码所示,callable的核心是call方法,允许返回值,runnable的核心是run方法,没有返回值

3、call方法可以抛出异常,但是run方法不行

4、因为runnable是java1.1就有了,所以他不存在返回值,后期在java1.5进行了优化,就出现了callable,就有了返回值和抛异常

5、callable和runnable都可以应用于executors。而thread类只支持runnable

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。