线程创建方式

Posted wuhao-0206

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程创建方式相关的知识,希望对你有一定的参考价值。

一、继承Thread类,重写run方法,实现创建一个线程
package com.wuhao.thread;

import java.util.Date;

/**
 * 自定义线程
 */
public class MyThread extends Thread{
    public void run() {
        for (int i = 0;i<10;i++
        ){
            System.out.println("子线程执行时间:"+new Date().getTime());
        }
    }
}


package com.wuhao.thread;

import java.util.Date;

/**
 * 测试类
 */
public class ThreadTest {

    public static void main(String[] args) {
        //1.创建自定义线程实例
        MyThread myThread = new MyThread();
        //2、启动线程
        myThread.start();
        //3、执行main主线程
        for (int i = 0;i<10;i++){
            System.out.println("主线程执行时间:"+new Date().getTime());
        }
    }
}


"C:Program FilesJavajdk1.8.0_131injava.exe" "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2018.2.5libidea_rt.jar=63359:C:Program FilesJetBrainsIntelliJ IDEA 2018.2.5in" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_131jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_131jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_131jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_131jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_131jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_131jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_131jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_131jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_131jrelibext
ashorn.jar;C:Program FilesJavajdk1.8.0_131jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_131jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_131jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_131jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_131jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_131jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_131jrelibjce.jar;C:Program FilesJavajdk1.8.0_131jrelibjfr.jar;C:Program FilesJavajdk1.8.0_131jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_131jrelibjsse.jar;C:Program FilesJavajdk1.8.0_131jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_131jrelibplugin.jar;C:Program FilesJavajdk1.8.0_131jrelib
esources.jar;C:Program FilesJavajdk1.8.0_131jrelib
t.jar;C:UsersAdministratorIdeaProjectsmultiThread	hread_create_demo	argetclasses" com.wuhao.thread.ThreadTest
主线程执行时间:1589007456050
子线程执行时间:1589007456050
主线程执行时间:1589007456050
子线程执行时间:1589007456051
主线程执行时间:1589007456051
子线程执行时间:1589007456051
子线程执行时间:1589007456051
子线程执行时间:1589007456051
子线程执行时间:1589007456051
子线程执行时间:1589007456051
子线程执行时间:1589007456051
子线程执行时间:1589007456051
主线程执行时间:1589007456051
主线程执行时间:1589007456051
主线程执行时间:1589007456051
子线程执行时间:1589007456051
主线程执行时间:1589007456051
主线程执行时间:1589007456051
主线程执行时间:1589007456051
主线程执行时间:1589007456051

Process finished with exit code 0


总结:
从上述执行时间来看,主子线程执行时间上具有重叠部分,说明主子线程可以并发执行。
二、实现Runnable接口重写run方法实现线程的创建
package com.wuhao.thread;

import java.util.Date;

/**
 * 自定义实现Runnable接口实现创建线程
 */
public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+""+i+"执行时间:"+new Date().getTime());
        }
    }
}


package com.wuhao.thread;

import java.util.Date;

/**
 * 测试类
 */
public class ThreadTest {

    public static void main(String[] args) {
        //1、main主线程打印信息
        for (int i = 0;i<10;i++){
            System.out.println("主线程执行时间:"+new Date().getTime());
        }
        //2、通过thread类执行MyRunnable类
        Thread thread = new Thread(new MyRunnable());
        thread.start();
    }
    }



"C:Program FilesJavajdk1.8.0_131injava.exe" "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2018.2.5libidea_rt.jar=63249:C:Program FilesJetBrainsIntelliJ IDEA 2018.2.5in" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_131jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_131jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_131jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_131jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_131jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_131jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_131jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_131jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_131jrelibext
ashorn.jar;C:Program FilesJavajdk1.8.0_131jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_131jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_131jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_131jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_131jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_131jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_131jrelibjce.jar;C:Program FilesJavajdk1.8.0_131jrelibjfr.jar;C:Program FilesJavajdk1.8.0_131jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_131jrelibjsse.jar;C:Program FilesJavajdk1.8.0_131jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_131jrelibplugin.jar;C:Program FilesJavajdk1.8.0_131jrelib
esources.jar;C:Program FilesJavajdk1.8.0_131jrelib
t.jar;C:UsersAdministratorIdeaProjectsmultiThread	hread_create_demo	argetclasses" com.wuhao.thread.ThreadTest
主线程执行时间:1589008598569
主线程执行时间:1589008598569
主线程执行时间:1589008598569
主线程执行时间:1589008598569
主线程执行时间:1589008598569
主线程执行时间:1589008598569
主线程执行时间:1589008598569
主线程执行时间:1589008598569
主线程执行时间:1589008598569
主线程执行时间:1589008598569
Thread-0第0执行时间:1589008598582
Thread-0第1执行时间:1589008598582
Thread-0第2执行时间:1589008598582
Thread-0第3执行时间:1589008598582
Thread-0第4执行时间:1589008598582
Thread-0第5执行时间:1589008598582
Thread-0第6执行时间:1589008598582
Thread-0第7执行时间:1589008598582
Thread-0第8执行时间:1589008598582
Thread-0第9执行时间:1589008598582

Process finished with exit code 0


总结:
由线程执行时间可以看出,实现了主子线程的创建
三、实现callable接口实现
FutrueTask 实现RunnableFutrue接口,制定返回值泛型类型,RunnableFutrue继承Runnable接口和Futrue,
重新call方法,具有返回值
package com.wuhao.thread;

import java.util.Date;
import java.util.concurrent.Callable;

/**
 * 自定义实现Callable接口创建线程
 */
public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        for (int i = 0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+""+i+"次执行时间:"+new Date().getTime());
        }
        return "子线程执行完毕";
    }
}


package com.wuhao.thread;

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

/**
 * 测试类
 */
public class ThreadTest {

    public static void main(String[] args) {
        //1、main主线程打印信息
        for (int i = 0; i < 10; i++) {
            System.out.println("主线程执行时间:" + new Date().getTime());
        }
        //2、创建FutrueTask实例,创建Callable接口
        //3、创建Thread实例,执行FutrueTask
        //4、获取打印子线程执行结果
        FutureTask<String> task = new FutureTask<>( new MyCallable());
        Thread thread = new Thread(task,"myCallable");
        thread.start();
        try {
            String result = task.get();
            System.out.println("子线程执行结果:"+result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}


"C:Program FilesJavajdk1.8.0_131injava.exe" "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2018.2.5libidea_rt.jar=63390:C:Program FilesJetBrainsIntelliJ IDEA 2018.2.5in" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_131jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_131jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_131jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_131jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_131jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_131jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_131jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_131jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_131jrelibext
ashorn.jar;C:Program FilesJavajdk1.8.0_131jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_131jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_131jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_131jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_131jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_131jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_131jrelibjce.jar;C:Program FilesJavajdk1.8.0_131jrelibjfr.jar;C:Program FilesJavajdk1.8.0_131jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_131jrelibjsse.jar;C:Program FilesJavajdk1.8.0_131jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_131jrelibplugin.jar;C:Program FilesJavajdk1.8.0_131jrelib
esources.jar;C:Program FilesJavajdk1.8.0_131jrelib
t.jar;C:UsersAdministratorIdeaProjectsmultiThread	hread_create_demo	argetclasses" com.wuhao.thread.ThreadTest
主线程执行时间:1589009519143
主线程执行时间:1589009519144
主线程执行时间:1589009519144
主线程执行时间:1589009519144
主线程执行时间:1589009519144
主线程执行时间:1589009519144
主线程执行时间:1589009519144
主线程执行时间:1589009519144
主线程执行时间:1589009519144
主线程执行时间:1589009519144
myCallable第0次执行时间:1589009519147
myCallable第1次执行时间:1589009519147
myCallable第2次执行时间:1589009519147
myCallable第3次执行时间:1589009519147
myCallable第4次执行时间:1589009519147
myCallable第5次执行时间:1589009519147
myCallable第6次执行时间:1589009519147
myCallable第7次执行时间:1589009519147
myCallable第8次执行时间:1589009519147
myCallable第9次执行时间:1589009519147
子线程执行结果:子线程执行完毕

Process finished with exit code 0


四、通过线程池创建线程
线程池本质上是一个线程的容器,在开发中,需要创建线程的时候则直接去线程池中去拿线程,执行完毕后再释放资源,这种方式效率较高。
package com.wuhao.thread;

        import java.util.Date;

/**
 * 自定义实现Runnable接口实现创建线程
 */
public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+""+i+"执行时间:"+new Date().getTime());
        }
    }
}


package com.wuhao.thread;

import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 线程池测试类
 */
public class ThreadPoolTest {
    public static void main(String[] args) {
        //1、使用线程池创建线程,Executors获取线程对象
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        //2、通过线程池对象获取线程并执行MyRunnable实例
        executorService.execute(new MyRunnable());
        //3、主线程打印信息
        for (int i = 0; i < 10; i++) {
            System.out.println("主线程执行时间:" + new Date().getTime());
        }
    }
}


"C:Program FilesJavajdk1.8.0_131injava.exe" "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2018.2.5libidea_rt.jar=63507:C:Program FilesJetBrainsIntelliJ IDEA 2018.2.5in" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_131jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_131jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_131jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_131jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_131jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_131jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_131jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_131jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_131jrelibext
ashorn.jar;C:Program FilesJavajdk1.8.0_131jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_131jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_131jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_131jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_131jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_131jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_131jrelibjce.jar;C:Program FilesJavajdk1.8.0_131jrelibjfr.jar;C:Program FilesJavajdk1.8.0_131jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_131jrelibjsse.jar;C:Program FilesJavajdk1.8.0_131jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_131jrelibplugin.jar;C:Program FilesJavajdk1.8.0_131jrelib
esources.jar;C:Program FilesJavajdk1.8.0_131jrelib
t.jar;C:UsersAdministratorIdeaProjectsmultiThread	hread_create_demo	argetclasses" com.wuhao.thread.ThreadPoolTest
主线程执行时间:1589010338954
pool-1-thread-1第0执行时间:1589010338954
主线程执行时间:1589010338954
pool-1-thread-1第1执行时间:1589010338954
主线程执行时间:1589010338954
pool-1-thread-1第2执行时间:1589010338954
主线程执行时间:1589010338954
pool-1-thread-1第3执行时间:1589010338954
主线程执行时间:1589010338954
pool-1-thread-1第4执行时间:1589010338954
主线程执行时间:1589010338954
pool-1-thread-1第5执行时间:1589010338954
主线程执行时间:1589010338954
pool-1-thread-1第6执行时间:1589010338954
主线程执行时间:1589010338954
pool-1-thread-1第7执行时间:1589010338954
主线程执行时间:1589010338954
pool-1-thread-1第8执行时间:1589010338954
主线程执行时间:1589010338954
pool-1-thread-1第9执行时间:1589010338954


实现线程创建方式总结:
1、实现接口和Thread类比较
接口适合多个相同程序代码的线程去共享同一资源
接口避免了java中单继承的局限性
接口代码可以多个线程共享,代码和线程独立
线程池只能放入实现Runnable或者Callable接口的线程,不能直接放入Thread的类
java中,每次至少运行两个线程,一个是main主线程,另一个是垃圾收集线程
2、Runnable和Callable接口比较
相同点:
两者都是接口
两者都可以编写多线程接口
两者都需要调用Thread.start()方法启动线程
不同点:
Callable可以返回执行结果,Runnable不需要返回执行结果
Callable接口的call()方法允许抛出异常,Runable接口的run()不允许抛出异常
实现Callable接口可以调用Future.cancle()取消线程的执行,而Runnable接口执行则不能取消
Callable接口中执行返回结果时,需要调用FutrueTask.get()方法实现,此方法会阻塞主线程直接去获取子线程执行结果,当不调用此方法,主线程则不阻塞。

 

以上是关于线程创建方式的主要内容,如果未能解决你的问题,请参考以下文章

线程池与并行度

IDEA对新建java线程池的建议

在 Visual Studio 中创建构造函数的代码片段或快捷方式

JavaSE线程基础

保存以编程方式为片段创建的视图并在 onresume 中恢复

多个请求是多线程吗