前言
线程,英文Thread。在java中,创建线程的方式有三种:
1、Thread
2、Runnable
3、Callable
在详细介绍下这几种方式之前,我们先来看下Thread类和Runnable接口。
Runnable接口
接口中只有一个run()方法,等待实现类去实现。
- package java.lang;
- @FunctionalInterface
- public interface Runnable {
-
- public abstract void run();
- }
Thread类
该类实现了Runnable接口,也提供了很多其他的方法,如yield(),join()等
- package java.lang;
- public
- class Thread implements Runnable {
- //获取当前线程
- public static native Thread currentThread();
- public static native void yield();
- //一系列的构造函数
- public Thread(Runnable target, String name) {
- init(null, target, name, 0);
- }
- public Thread(ThreadGroup group, String name) {
- init(group, null, name, 0);
- }
- /*调用该方法时,jvm会调用run方法
- *Causes this thread to begin execution; the Java Virtual Machine
- * calls the run method of this thread.
- */
- public synchronized void start() {
-
- if (threadStatus != 0)
- throw new IllegalThreadStateException();
-
- group.add(this);
-
- boolean started = false;
- try {
- start0();
- started = true;
- } finally {
- try {
- if (!started) {
- group.threadStartFailed(this);
- }
- } catch (Throwable ignore) {
-
- }
- }
- }
-
- }
一、实现Runnable接口
- public class i_Runnable {
-
- /**
- * 主线程main方法
- * @param args
- */
- public static void main(String[] args) {
- for (int i = 0; i < 100; i++) {
- System.out.println(Thread.currentThread().getName() + "====" + i);
- if (i == 20) {
- RunnableThreadTest rtt = new RunnableThreadTest();
- //子线程
- new Thread(rtt, "new Thread[1]====").start();
- //new Thread(rtt, "新线程2").start();
- }
- }
-
- }
- /**
- * RunnableThreadTest实现Runnable接口
- * @author YANG
- *
- */
- static class RunnableThreadTest implements Runnable {
- private int i;
-
- @Override
- public void run() {
- for (i = 0; i < 100; i++) {
- System.out.println(Thread.currentThread().getName() + " " + i);
- }
-
- }
-
- }
- }
执行结果:
注意:
** 执行结果只截取了部分内容。
** 如果RunnableThreadTest类前不加static,会报错No enclosing instance of type i_Runnable is accessible. Must qualify the allocation with an enclosin。因为只有内部类修饰为静态时,才可以在静态类方法(main方法)中调用该类的成员变量和方法。
二、继承Thread类
- public class a_Thread {
- public static void main(String[] args) {
- Runner1 r=new Runner1();
- r.start(); //已经有thread 不需要new,直接调用start即可。
-
-
- for (int i = 0; i < 100; i++) {
- System.out.println("main Thread:"+i);
- }
- }
-
- //Runner1继承Thread类,重写run方法
- static class Runner1 extends Thread{
- @Override
- public void run() {
-
- for (int i = 0; i < 100; i++) {
- System.out.println("Runner1:"+i);
- }
-
- }
-
- }
- }
分析:换成run()方法之后,就变成了普通的方法调用,只有一个主线程,没有子线程。
执行结果:为了方便显示,我们将循环次数改为10。
- Runner1:0
- Runner1:1
- Runner1:2
- Runner1:3
- Runner1:4
- Runner1:5
- Runner1:6
- Runner1:7
- Runner1:8
- Runner1:9
- main Thread:0
- main Thread:1
- main Thread:2
- main Thread:3
- main Thread:4
- main Thread:5
- main Thread:6
- main Thread:7
- main Thread:8
- main Thread:9
三、实现Callable接口
前面两种方式是传统的线程技术中的内容,第三种方式Callable和Future是jdk1.5之后新增的。我们先来补充点东西,看看这种方式与之前的方式有什么联系。
- //实现Callable接口
- public class j_CallableTest implements Callable<String> {
- public static void main(String[] args) {
- j_CallableTest test=new j_CallableTest();
- FutureTask<String> ft=new FutureTask<>(test);
-
- for (int i = 0; i < 100; i++) {
- System.out.println(Thread.currentThread().getName()+" i的值为="+i);
- if(i==20){
- new Thread(ft,"子线程").start();
- }
- }
- }
-
- //重写call方法
- @Override
- public String call() throws Exception {
- int i = 0;
- String reString = "";
- for (; i < 100; i++) {
- reString = Thread.currentThread().getName() + " " + i;
- System.out.println(reString);
- }
- return reString;
- }
- }
从上面可以看到,new Thread的方式还是用的public Thread(Runnable target, String name); 说明FutureTask也是Runnable类型的,他们之间的关系可以从下图中看出来。
那么,使用Callable和Future的方式有什么特点呢?
我们从他们的定义来看,Callable接口中只有一个方法,返回值为V。前两种方式都是返回void。
- @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;
- }
小结:
1、接口实现更灵活,java不支持多继承。在这方面,Runnable和Callable更有优势。
2、返回值问题。Runnable和Thread都不能有返回值,但Callable可以,而且支持多种类型的数据。
就这两点来看,新增的Callable和Future的实现方式优势十分明显啊。但是追到原理,其实这三种都可以归结为一种方式。