一、继承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()方法实现,此方法会阻塞主线程直接去获取子线程执行结果,当不调用此方法,主线程则不阻塞。