Java中实现多线程的3种方法介绍和比较

3种方法

  1. 继承Thread类
  2. 实现Runnable接口
  3. 实现Callable接口

继承Thread类

继承Thread类,覆盖run()方法,在创建Thread类的子类时需要重写 run(),加入线程所要执行的任务代码

自定义类继承Thread类:

package com.ahut.thread;

/**
 * @author cheng
 * @className: MyThread
 * @description:
 * @dateTime 2018/6/4 15:43
 */
public class MyThread extends Thread {

    private String threadName;

    MyThread(String threadName) {
        this.threadName = threadName;
    }

    /**
     * @description:
     * @author cheng
     * @dateTime 2018/6/4 15:43
     */
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("当前线程名:" + threadName + ",循环的次数:" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

测试:

package com.ahut.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @author cheng
 * @className: ThreadMain
 * @description:
 * @dateTime 2018/6/4 15:46
 */
public class ThreadMain {

    /**
     * @description: 主函数
     * @author cheng
     * @dateTime 2018/6/4 15:46
     */
    public static void main(String[] args){

        // 创建线程
        MyThread myThread1 = new MyThread("thread-1");
        MyThread myThread2 = new MyThread("thread-2");

        // 启动线程
        myThread1.start();
        myThread2.start();

    }

}

运行结果:

"C:\Program Files\Java\jdk1.8.0_131\bin\java" "-javaagent:F:\IDEA\IntelliJ IDEA 2017.3.4\lib\idea_rt.jar=57465:F:\IDEA\IntelliJ IDEA 2017.3.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_131\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar;D:\IDEA workspace\ahut-dubbo\ahut-redis\target\test-classes;D:\IDEA workspace\ahut-dubbo\ahut-redis\target\classes;C:\Users\rick\.m2\repository\redis\clients\jedis\2.9.0\jedis-2.9.0.jar;C:\Users\rick\.m2\repository\org\apache\commons\commons-pool2\2.5.0\commons-pool2-2.5.0.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter-web\2.0.2.RELEASE\spring-boot-starter-web-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter\2.0.2.RELEASE\spring-boot-starter-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot\2.0.2.RELEASE\spring-boot-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.0.2.RELEASE\spring-boot-autoconfigure-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.0.2.RELEASE\spring-boot-starter-logging-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\Users\rick\.m2\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\Users\rick\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.10.0\log4j-to-slf4j-2.10.0.jar;C:\Users\rick\.m2\repository\org\apache\logging\log4j\log4j-api\2.10.0\log4j-api-2.10.0.jar;C:\Users\rick\.m2\repository\org\slf4j\jul-to-slf4j\1.7.25\jul-to-slf4j-1.7.25.jar;C:\Users\rick\.m2\repository\javax\annotation\javax.annotation-api\1.3.2\javax.annotation-api-1.3.2.jar;C:\Users\rick\.m2\repository\org\yaml\snakeyaml\1.19\snakeyaml-1.19.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter-json\2.0.2.RELEASE\spring-boot-starter-json-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.9.5\jackson-databind-2.9.5.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.9.0\jackson-annotations-2.9.0.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.9.5\jackson-core-2.9.5.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.9.5\jackson-datatype-jdk8-2.9.5.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.9.5\jackson-datatype-jsr310-2.9.5.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.9.5\jackson-module-parameter-names-2.9.5.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\2.0.2.RELEASE\spring-boot-starter-tomcat-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\8.5.31\tomcat-embed-core-8.5.31.jar;C:\Users\rick\.m2\repository\org\apache\tomcat\embed\tomcat-embed-el\8.5.31\tomcat-embed-el-8.5.31.jar;C:\Users\rick\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\8.5.31\tomcat-embed-websocket-8.5.31.jar;C:\Users\rick\.m2\repository\org\hibernate\validator\hibernate-validator\6.0.9.Final\hibernate-validator-6.0.9.Final.jar;C:\Users\rick\.m2\repository\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar;C:\Users\rick\.m2\repository\org\jboss\logging\jboss-logging\3.3.2.Final\jboss-logging-3.3.2.Final.jar;C:\Users\rick\.m2\repository\com\fasterxml\classmate\1.3.4\classmate-1.3.4.jar;C:\Users\rick\.m2\repository\org\springframework\spring-web\5.0.6.RELEASE\spring-web-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-beans\5.0.6.RELEASE\spring-beans-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-webmvc\5.0.6.RELEASE\spring-webmvc-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-aop\5.0.6.RELEASE\spring-aop-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-context\5.0.6.RELEASE\spring-context-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-expression\5.0.6.RELEASE\spring-expression-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter-test\2.0.2.RELEASE\spring-boot-starter-test-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-test\2.0.2.RELEASE\spring-boot-test-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-test-autoconfigure\2.0.2.RELEASE\spring-boot-test-autoconfigure-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\com\jayway\jsonpath\json-path\2.4.0\json-path-2.4.0.jar;C:\Users\rick\.m2\repository\net\minidev\json-smart\2.3\json-smart-2.3.jar;C:\Users\rick\.m2\repository\net\minidev\accessors-smart\1.2\accessors-smart-1.2.jar;C:\Users\rick\.m2\repository\org\ow2\asm\asm\5.0.4\asm-5.0.4.jar;C:\Users\rick\.m2\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;C:\Users\rick\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\rick\.m2\repository\org\assertj\assertj-core\3.9.1\assertj-core-3.9.1.jar;C:\Users\rick\.m2\repository\org\mockito\mockito-core\2.15.0\mockito-core-2.15.0.jar;C:\Users\rick\.m2\repository\net\bytebuddy\byte-buddy\1.7.11\byte-buddy-1.7.11.jar;C:\Users\rick\.m2\repository\net\bytebuddy\byte-buddy-agent\1.7.11\byte-buddy-agent-1.7.11.jar;C:\Users\rick\.m2\repository\org\objenesis\objenesis\2.6\objenesis-2.6.jar;C:\Users\rick\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\Users\rick\.m2\repository\org\hamcrest\hamcrest-library\1.3\hamcrest-library-1.3.jar;C:\Users\rick\.m2\repository\org\skyscreamer\jsonassert\1.5.0\jsonassert-1.5.0.jar;C:\Users\rick\.m2\repository\com\vaadin\external\google\android-json\0.0.20131108.vaadin1\android-json-0.0.20131108.vaadin1.jar;C:\Users\rick\.m2\repository\org\springframework\spring-core\5.0.6.RELEASE\spring-core-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-jcl\5.0.6.RELEASE\spring-jcl-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-test\5.0.6.RELEASE\spring-test-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\xmlunit\xmlunit-core\2.5.1\xmlunit-core-2.5.1.jar" com.ahut.thread.ThreadMain
当前线程名:thread-1,循环的次数:0
当前线程名:thread-2,循环的次数:0
当前线程名:thread-2,循环的次数:1
当前线程名:thread-1,循环的次数:1
当前线程名:thread-1,循环的次数:2
当前线程名:thread-2,循环的次数:2
当前线程名:thread-1,循环的次数:3
当前线程名:thread-2,循环的次数:3
当前线程名:thread-1,循环的次数:4
当前线程名:thread-2,循环的次数:4
当前线程名:thread-1,循环的次数:5
当前线程名:thread-2,循环的次数:5
当前线程名:thread-1,循环的次数:6
当前线程名:thread-2,循环的次数:6
当前线程名:thread-1,循环的次数:7
当前线程名:thread-2,循环的次数:7
当前线程名:thread-1,循环的次数:8
当前线程名:thread-2,循环的次数:8
当前线程名:thread-1,循环的次数:9
当前线程名:thread-2,循环的次数:9

Process finished with exit code 0

实现Runnable接口

为了解决单继承的局限性,建议实现Runnable接口

Runnable是可以共享数据的,多个Thread可以同时加载一个Runnable,当各自Thread获得CPU时间片的时候开始运行Runnable,Runnable里面的资源是被共享的,所以使用Runnable更加的灵活

注意 :需要解决共享之后产生的资源竞争问题

自定义类实现Runnable接口:

package com.ahut.thread;

/**
 * @author cheng
 * @className: RunnableImpl
 * @description:
 * @dateTime 2018/6/4 16:14
 */
public class RunnableImpl implements Runnable {

    private String threadName;

    RunnableImpl(String threadName) {
        this.threadName = threadName;
    }

    /**
     * @description:
     * @author cheng
     * @dateTime 2018/6/4 15:43
     */
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("当前线程名:" + threadName + ",循环的次数:" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

测试:

package com.ahut.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @author cheng
 * @className: ThreadMain
 * @description:
 * @dateTime 2018/6/4 15:46
 */
public class ThreadMain {

    /**
     * @description: 主函数
     * @author cheng
     * @dateTime 2018/6/4 15:46
     */
    public static void main(String[] args){

        // 创建任务
        RunnableImpl runnableImpl1 = new RunnableImpl("runnable-1");
        RunnableImpl runnableImpl2 = new RunnableImpl("runnable-2");

        // 创建线程
        Thread thread1 = new Thread(runnableImpl1);
        Thread thread2 = new Thread(runnableImpl2);

        // 启动线程
        thread1.start();
        thread2.start();

    }

}

运行结果:

"C:\Program Files\Java\jdk1.8.0_131\bin\java" "-javaagent:F:\IDEA\IntelliJ IDEA 2017.3.4\lib\idea_rt.jar=57593:F:\IDEA\IntelliJ IDEA 2017.3.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_131\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar;D:\IDEA workspace\ahut-dubbo\ahut-redis\target\test-classes;D:\IDEA workspace\ahut-dubbo\ahut-redis\target\classes;C:\Users\rick\.m2\repository\redis\clients\jedis\2.9.0\jedis-2.9.0.jar;C:\Users\rick\.m2\repository\org\apache\commons\commons-pool2\2.5.0\commons-pool2-2.5.0.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter-web\2.0.2.RELEASE\spring-boot-starter-web-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter\2.0.2.RELEASE\spring-boot-starter-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot\2.0.2.RELEASE\spring-boot-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.0.2.RELEASE\spring-boot-autoconfigure-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.0.2.RELEASE\spring-boot-starter-logging-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\Users\rick\.m2\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\Users\rick\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.10.0\log4j-to-slf4j-2.10.0.jar;C:\Users\rick\.m2\repository\org\apache\logging\log4j\log4j-api\2.10.0\log4j-api-2.10.0.jar;C:\Users\rick\.m2\repository\org\slf4j\jul-to-slf4j\1.7.25\jul-to-slf4j-1.7.25.jar;C:\Users\rick\.m2\repository\javax\annotation\javax.annotation-api\1.3.2\javax.annotation-api-1.3.2.jar;C:\Users\rick\.m2\repository\org\yaml\snakeyaml\1.19\snakeyaml-1.19.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter-json\2.0.2.RELEASE\spring-boot-starter-json-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.9.5\jackson-databind-2.9.5.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.9.0\jackson-annotations-2.9.0.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.9.5\jackson-core-2.9.5.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.9.5\jackson-datatype-jdk8-2.9.5.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.9.5\jackson-datatype-jsr310-2.9.5.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.9.5\jackson-module-parameter-names-2.9.5.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\2.0.2.RELEASE\spring-boot-starter-tomcat-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\8.5.31\tomcat-embed-core-8.5.31.jar;C:\Users\rick\.m2\repository\org\apache\tomcat\embed\tomcat-embed-el\8.5.31\tomcat-embed-el-8.5.31.jar;C:\Users\rick\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\8.5.31\tomcat-embed-websocket-8.5.31.jar;C:\Users\rick\.m2\repository\org\hibernate\validator\hibernate-validator\6.0.9.Final\hibernate-validator-6.0.9.Final.jar;C:\Users\rick\.m2\repository\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar;C:\Users\rick\.m2\repository\org\jboss\logging\jboss-logging\3.3.2.Final\jboss-logging-3.3.2.Final.jar;C:\Users\rick\.m2\repository\com\fasterxml\classmate\1.3.4\classmate-1.3.4.jar;C:\Users\rick\.m2\repository\org\springframework\spring-web\5.0.6.RELEASE\spring-web-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-beans\5.0.6.RELEASE\spring-beans-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-webmvc\5.0.6.RELEASE\spring-webmvc-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-aop\5.0.6.RELEASE\spring-aop-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-context\5.0.6.RELEASE\spring-context-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-expression\5.0.6.RELEASE\spring-expression-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter-test\2.0.2.RELEASE\spring-boot-starter-test-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-test\2.0.2.RELEASE\spring-boot-test-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-test-autoconfigure\2.0.2.RELEASE\spring-boot-test-autoconfigure-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\com\jayway\jsonpath\json-path\2.4.0\json-path-2.4.0.jar;C:\Users\rick\.m2\repository\net\minidev\json-smart\2.3\json-smart-2.3.jar;C:\Users\rick\.m2\repository\net\minidev\accessors-smart\1.2\accessors-smart-1.2.jar;C:\Users\rick\.m2\repository\org\ow2\asm\asm\5.0.4\asm-5.0.4.jar;C:\Users\rick\.m2\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;C:\Users\rick\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\rick\.m2\repository\org\assertj\assertj-core\3.9.1\assertj-core-3.9.1.jar;C:\Users\rick\.m2\repository\org\mockito\mockito-core\2.15.0\mockito-core-2.15.0.jar;C:\Users\rick\.m2\repository\net\bytebuddy\byte-buddy\1.7.11\byte-buddy-1.7.11.jar;C:\Users\rick\.m2\repository\net\bytebuddy\byte-buddy-agent\1.7.11\byte-buddy-agent-1.7.11.jar;C:\Users\rick\.m2\repository\org\objenesis\objenesis\2.6\objenesis-2.6.jar;C:\Users\rick\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\Users\rick\.m2\repository\org\hamcrest\hamcrest-library\1.3\hamcrest-library-1.3.jar;C:\Users\rick\.m2\repository\org\skyscreamer\jsonassert\1.5.0\jsonassert-1.5.0.jar;C:\Users\rick\.m2\repository\com\vaadin\external\google\android-json\0.0.20131108.vaadin1\android-json-0.0.20131108.vaadin1.jar;C:\Users\rick\.m2\repository\org\springframework\spring-core\5.0.6.RELEASE\spring-core-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-jcl\5.0.6.RELEASE\spring-jcl-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-test\5.0.6.RELEASE\spring-test-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\xmlunit\xmlunit-core\2.5.1\xmlunit-core-2.5.1.jar" com.ahut.thread.ThreadMain
当前线程名:runnable-1,循环的次数:0
当前线程名:runnable-2,循环的次数:0
当前线程名:runnable-2,循环的次数:1
当前线程名:runnable-1,循环的次数:1
当前线程名:runnable-2,循环的次数:2
当前线程名:runnable-1,循环的次数:2
当前线程名:runnable-1,循环的次数:3
当前线程名:runnable-2,循环的次数:3
当前线程名:runnable-2,循环的次数:4
当前线程名:runnable-1,循环的次数:4
当前线程名:runnable-2,循环的次数:5
当前线程名:runnable-1,循环的次数:5
当前线程名:runnable-2,循环的次数:6
当前线程名:runnable-1,循环的次数:6
当前线程名:runnable-2,循环的次数:7
当前线程名:runnable-1,循环的次数:7
当前线程名:runnable-2,循环的次数:8
当前线程名:runnable-1,循环的次数:8
当前线程名:runnable-2,循环的次数:9
当前线程名:runnable-1,循环的次数:9

Process finished with exit code 0

实现Callable接口

Runnable是执行工作的独立任务,但是它不返回任何值。如果你希望任务在完成的能返回一个值,那么可以实现Callable接口而不是Runnable接口。

在Java SE5中引入的Callable是一种具有类型参数的泛型,它的参数类型表示的是从方法call()(不是run())中返回的值。

自定义类实现Callable接口:

package com.ahut.thread;

import java.util.concurrent.Callable;

/**
 * @author cheng
 * @className: CallableImpl
 * @description:
 * @dateTime 2018/6/4 16:15
 */
public class CallableImpl implements Callable<Boolean> {

    private String threadName;

    CallableImpl(String threadName) {
        this.threadName = threadName;
    }

    /**
     * @description:
     * @author cheng
     * @dateTime 2018/6/4 16:53
     */
    @Override
    public Boolean call() throws Exception {
        for (int i = 0; i < 10; i++) {
            System.out.println("当前线程名:" + threadName + ",循环的次数:" + i);
            Thread.sleep(500);
        }
        return true;
    }

}

测试:

package com.ahut.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @author cheng
 * @className: ThreadMain
 * @description:
 * @dateTime 2018/6/4 15:46
 */
public class ThreadMain {

    /**
     * @description: 主函数
     * @author cheng
     * @dateTime 2018/6/4 15:46
     */
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        // 创建任务
        CallableImpl callable1 = new CallableImpl("callable-1");
        CallableImpl callable2 = new CallableImpl("callable-2");

        // 获取返回结果
        FutureTask<Boolean> futureTask1 = new FutureTask<>(callable1);
        FutureTask<Boolean> futureTask2 = new FutureTask<>(callable2);

        // 创建线程
        new Thread(futureTask1).start();
        new Thread(futureTask2).start();

        long startTime1 = System.currentTimeMillis();
        boolean flag1 = futureTask1.get();
        System.out.println("返回结果:" + flag1);
        long endTime1 = System.currentTimeMillis();
        System.out.println("阻塞时间:" + (endTime1 - startTime1));

        long startTime2 = System.currentTimeMillis();
        boolean flag2 = futureTask2.get();
        System.out.println("返回结果:" + flag2);
        long endTime2 = System.currentTimeMillis();
        System.out.println("阻塞时间:" + (endTime2 - startTime2));
    }

}

运行结果:

"C:\Program Files\Java\jdk1.8.0_131\bin\java" "-javaagent:F:\IDEA\IntelliJ IDEA 2017.3.4\lib\idea_rt.jar=57627:F:\IDEA\IntelliJ IDEA 2017.3.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_131\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar;D:\IDEA workspace\ahut-dubbo\ahut-redis\target\test-classes;D:\IDEA workspace\ahut-dubbo\ahut-redis\target\classes;C:\Users\rick\.m2\repository\redis\clients\jedis\2.9.0\jedis-2.9.0.jar;C:\Users\rick\.m2\repository\org\apache\commons\commons-pool2\2.5.0\commons-pool2-2.5.0.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter-web\2.0.2.RELEASE\spring-boot-starter-web-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter\2.0.2.RELEASE\spring-boot-starter-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot\2.0.2.RELEASE\spring-boot-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.0.2.RELEASE\spring-boot-autoconfigure-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.0.2.RELEASE\spring-boot-starter-logging-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\Users\rick\.m2\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\Users\rick\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.10.0\log4j-to-slf4j-2.10.0.jar;C:\Users\rick\.m2\repository\org\apache\logging\log4j\log4j-api\2.10.0\log4j-api-2.10.0.jar;C:\Users\rick\.m2\repository\org\slf4j\jul-to-slf4j\1.7.25\jul-to-slf4j-1.7.25.jar;C:\Users\rick\.m2\repository\javax\annotation\javax.annotation-api\1.3.2\javax.annotation-api-1.3.2.jar;C:\Users\rick\.m2\repository\org\yaml\snakeyaml\1.19\snakeyaml-1.19.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter-json\2.0.2.RELEASE\spring-boot-starter-json-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.9.5\jackson-databind-2.9.5.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.9.0\jackson-annotations-2.9.0.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.9.5\jackson-core-2.9.5.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.9.5\jackson-datatype-jdk8-2.9.5.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.9.5\jackson-datatype-jsr310-2.9.5.jar;C:\Users\rick\.m2\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.9.5\jackson-module-parameter-names-2.9.5.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\2.0.2.RELEASE\spring-boot-starter-tomcat-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\8.5.31\tomcat-embed-core-8.5.31.jar;C:\Users\rick\.m2\repository\org\apache\tomcat\embed\tomcat-embed-el\8.5.31\tomcat-embed-el-8.5.31.jar;C:\Users\rick\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\8.5.31\tomcat-embed-websocket-8.5.31.jar;C:\Users\rick\.m2\repository\org\hibernate\validator\hibernate-validator\6.0.9.Final\hibernate-validator-6.0.9.Final.jar;C:\Users\rick\.m2\repository\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar;C:\Users\rick\.m2\repository\org\jboss\logging\jboss-logging\3.3.2.Final\jboss-logging-3.3.2.Final.jar;C:\Users\rick\.m2\repository\com\fasterxml\classmate\1.3.4\classmate-1.3.4.jar;C:\Users\rick\.m2\repository\org\springframework\spring-web\5.0.6.RELEASE\spring-web-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-beans\5.0.6.RELEASE\spring-beans-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-webmvc\5.0.6.RELEASE\spring-webmvc-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-aop\5.0.6.RELEASE\spring-aop-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-context\5.0.6.RELEASE\spring-context-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-expression\5.0.6.RELEASE\spring-expression-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-starter-test\2.0.2.RELEASE\spring-boot-starter-test-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-test\2.0.2.RELEASE\spring-boot-test-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\boot\spring-boot-test-autoconfigure\2.0.2.RELEASE\spring-boot-test-autoconfigure-2.0.2.RELEASE.jar;C:\Users\rick\.m2\repository\com\jayway\jsonpath\json-path\2.4.0\json-path-2.4.0.jar;C:\Users\rick\.m2\repository\net\minidev\json-smart\2.3\json-smart-2.3.jar;C:\Users\rick\.m2\repository\net\minidev\accessors-smart\1.2\accessors-smart-1.2.jar;C:\Users\rick\.m2\repository\org\ow2\asm\asm\5.0.4\asm-5.0.4.jar;C:\Users\rick\.m2\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;C:\Users\rick\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\rick\.m2\repository\org\assertj\assertj-core\3.9.1\assertj-core-3.9.1.jar;C:\Users\rick\.m2\repository\org\mockito\mockito-core\2.15.0\mockito-core-2.15.0.jar;C:\Users\rick\.m2\repository\net\bytebuddy\byte-buddy\1.7.11\byte-buddy-1.7.11.jar;C:\Users\rick\.m2\repository\net\bytebuddy\byte-buddy-agent\1.7.11\byte-buddy-agent-1.7.11.jar;C:\Users\rick\.m2\repository\org\objenesis\objenesis\2.6\objenesis-2.6.jar;C:\Users\rick\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\Users\rick\.m2\repository\org\hamcrest\hamcrest-library\1.3\hamcrest-library-1.3.jar;C:\Users\rick\.m2\repository\org\skyscreamer\jsonassert\1.5.0\jsonassert-1.5.0.jar;C:\Users\rick\.m2\repository\com\vaadin\external\google\android-json\0.0.20131108.vaadin1\android-json-0.0.20131108.vaadin1.jar;C:\Users\rick\.m2\repository\org\springframework\spring-core\5.0.6.RELEASE\spring-core-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-jcl\5.0.6.RELEASE\spring-jcl-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\springframework\spring-test\5.0.6.RELEASE\spring-test-5.0.6.RELEASE.jar;C:\Users\rick\.m2\repository\org\xmlunit\xmlunit-core\2.5.1\xmlunit-core-2.5.1.jar" com.ahut.thread.ThreadMain
当前线程名:callable-1,循环的次数:0
当前线程名:callable-2,循环的次数:0
当前线程名:callable-2,循环的次数:1
当前线程名:callable-1,循环的次数:1
当前线程名:callable-2,循环的次数:2
当前线程名:callable-1,循环的次数:2
当前线程名:callable-1,循环的次数:3
当前线程名:callable-2,循环的次数:3
当前线程名:callable-1,循环的次数:4
当前线程名:callable-2,循环的次数:4
当前线程名:callable-2,循环的次数:5
当前线程名:callable-1,循环的次数:5
当前线程名:callable-2,循环的次数:6
当前线程名:callable-1,循环的次数:6
当前线程名:callable-2,循环的次数:7
当前线程名:callable-1,循环的次数:7
当前线程名:callable-1,循环的次数:8
当前线程名:callable-2,循环的次数:8
当前线程名:callable-1,循环的次数:9
当前线程名:callable-2,循环的次数:9
返回结果:true
阻塞时间:5051
返回结果:true
阻塞时间:0

Process finished with exit code 0

三种方法的比较

实现Runnable接口相比继承Thread类有如下优势

  1. 可以避免由于Java的单继承特性而带来的局限
  2. 增强程序的健壮性,代码能够被多个线程共享,代码与数据是独立的
  3. 适合多个相同程序代码的线程去处理同一资源的情况
  4. 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类

实现Runnable接口和实现Callable接口的区别

  1. Runnable是自从java1.1就有了,而Callable是1.5之后才加上去的
  2. 实现Callable接口的任务线程能返回执行结果,而实现Runnable接口的任务线程不能返回结果
  3. Callable接口的call()方法允许抛出异常,而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛
  4. 加入线程池运行,Runnable使用ExecutorService的execute方法,Callable使用submit方法
  5. Callable接口支持返回执行结果,此时需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取返回结果,当不调用此方法时,主线程不会阻塞

猜你喜欢

转载自blog.csdn.net/qq_28988969/article/details/80569412