线程的三种方式
什么是线程,什么是进程
程序运行起 这个叫做进程 最小执行单元是线程
线程实现的三种方式
继承Thread
public class ExThreadTest extends Thread {
@Override
public void run() {
// super.run();
System.out.println(this.getName());
}
public static void main(String[] args) throws Exception {
// 1 继承Thread 实现其run方法进行线程的调用 调用使用start 方法 而不是run 方法
Thread thread1 = new ExThreadTest();
thread1.setName("startThread");
Thread thread2 = new ExThreadTest();
thread2.setName("runThread");
// 2 开始测试不同 为什么不调用run 方法
System.out.println("start 开始");
thread1.start();
System.out.println("start 打印语句结束");
Thread.sleep(1000);
System.out.println("------------");
System.out.println("------------");
System.out.println("run 开始");
thread2.run();
System.out.println("run 打印语句结束");
}
}
结果如下
不调用run 方法 是因为run 方法是跟主线程 一起执行的 需要按照主线程的执行顺序
而start 方法是在调用的时候开出一个分支 进行线程的调用
再看源码 其中run 方法是
@Override
public void run() {
if (target != null) {
target.run();
}
}
/* What will be run. */
private Runnable target;
一开始就申明了 target 再看构造方法和上面的英文 Runnable 去实现的
Thread 也是implements Runnable 去实现了 Runnable
start是调用start0 方法进行启动的 start0 被native 关键字所修饰。native 关键字表示是c 之类的更加底层的代码去实现了
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 */
}
}
}
实现Runnable 接口
public class ImRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable--------");
}
public static void main(String[] args) {
System.out.println("------------");
new ImRunnable().run();
System.out.println("------------");
new Thread(new ImRunnable()).start();
}
}
调用的话 继承Runnable 并没有start 这个方法 那么要不直接调用run方法,但是这个占主线程
要不就是给其另外一个实现类。也就是Thread 来进行传入后实现 因为是继承的,复用性比第一种大 。
实现Callable
public class ImCallable implements Callable {
public static void main(String[] args) throws Exception{
Object a= new ImCallable().call();
System.out.println(a);
}
@Override
public Object call() throws Exception {
return 1;
}
}
其实可以说继承的是一个泛型的接口 不定义的话是object 并且是有返回值的
那么具体的实现代码如下
public class ImCallable implements Callable {
public static void main(String[] args) throws Exception {
FutureTask futureTask = new FutureTask(new ImCallable());
new Thread(futureTask).start();
// 获取返回值
Object o = futureTask.get();
System.out.println(o);
}
@Override
public Object call() throws Exception {
System.out.println("Callable");
return 1;
}
}
当然实际应用中一般会捕获异常
现在我们来看一下FutureTask 他是实现了RunnableFuture 这个接口 而这个RunnableFuture接口又extends 了Runnable 所以可以看出这个方法的调用和第二种类似 不过是可以有一个自定义的返回值
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}