线程(三)——多线程的实现方式
来源:互联网 发布:c语言杨辉直角三角形 编辑:程序博客网 时间:2024/06/15 19:35
一.继承Thread类
步骤
1.定义一个类继承Teread线程类
2.重写Thread类的run方法
3.将要执行的程序写入run方法
4.用线程类的start()方法启动线程
package com.xin.thread.demo01_ExtendsThread;public class _Main { public static void main(String[] args) { MyThread mt = new MyThread(); //如果调用start方法,程序没用输出结果 mt.start();//用线程类的start()方法就会调用重写的run()方法 for (int i = 0; i < 1000; i++) { System.out.println(Thread.currentThread().getName()+"线程输出:"+i); } }}class MyThread extends Thread {//定义一个类继承Teread线程类 @Override public void run() {//重写Thread类的run方法,将要执行的程序放进run方法 for (int i = 0; i < 1000; i++) { System.out.println(Thread.currentThread().getName()+"线程输出:"+i); } }}
输出结果(片段):
main线程输出:351Thread-0线程输出:306main线程输出:352Thread-0线程输出:307Thread-0线程输出:308Thread-0线程输出:309
小结:
查看api文档说明start()方法的作用是使该线程开始执行,Java 虚拟机调用该线程的 run 方法( 而run方法只是一个普通的方法,并不会开启一条线程)。
public class TestRunAndStart { public static void main(String[] args) { new Thread("线程一") { @Override public void run() { super.run(); System.out.println(Thread.currentThread().getName()); } }.start(); new Thread("线程二") { @Override public void run() { super.run(); System.out.println(Thread.currentThread().getName()); } }.run(); }}
测试结果:
main线程一
注:多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动(start()方法中会判断threadStatus字段的值是否为零,如果不为零则抛出IllegalThreadStateException)。
二.实现Runnable接口
步骤:
1.定义一个类实现Runnable接口
2.实现Runnable接口的run方法
3.将要执行的程序写入run方法
4.用线程类的start()方法启动线程
package com.xin.thread.demo02_ImplementsRunnable;public class _Main { public static void main(String[] args) { Thread t = new Thread(new MyRunnable());//创建线程类,将MyRunnable作为Thread中的target创建新的线程 t.start();//用线程类的start()方法就会调用重写的run()方法 for (int i = 0; i < 1000; i++) { System.out.println(Thread.currentThread().getName() + "线程输出:" + i); } }}class MyRunnable implements Runnable {//定义一个类实现Runnable接口 @Override //重写Thread类的run方法 public void run() {//将要执行的程序放进run方法 for (int i = 0; i < 1000; i++) { System.out.println(Thread.currentThread().getName() + "线程输出:" + i); } }}
输出结果(片段):
Thread-0线程输出:625main线程输出:730Thread-0线程输出:626main线程输出:731main线程输出:732main线程输出:733
小结:
查看Thread类的构造方法发现public Thread(Runnable target)方法时将传入的参数赋值给Thread的target字段,而run()方法的源码如下,判断target字段是否为空(而我们通过构造函数将自定义的Runnable接口的实现传递给了target),如果不为空则调用其run方法。
@Override public void run() { if (target != null) { target.run(); } }
三.实现Callable接口
步骤:
1.定义一个类实现Callable接口
2.实现Callable接口的call方法
3.将要执行的程序写入call方法中
4.用FutureTask类来包装Callable接口实现类的对象
5.创建Thread对象并将第4步中的FutureTask对象传递进去
6.用线程类的start()方法启动线程
7.可以调用第4步创建的FutureTask对象的get方法返回第3步重写的call方法的返回值。
package com.xin.thread.demo04_ImplementsCallable;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.FutureTask;public class _Main_NewThread { public static void main(String[] args) { Callable c = new MyCallable(); FutureTask<String> task = new FutureTask<String>(c); Thread t = new Thread(task); t.start(); try { System.out.println(task.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println("主线程运行结束"); }}
package com.xin.thread.demo04_ImplementsCallable;import java.util.concurrent.Callable;class MyCallable implements Callable<String> { @Override public String call() throws Exception { System.out.println(Thread.currentThread().getName() + "的call方法运行中"); return Thread.currentThread().getName() + "的call方法结束"; }}
输出结果:
Thread-0的call方法运行中Thread-0的call方法结束主线程运行结束
小结:
实际上也是调用Thread的run方法,方法的实现是FutureTask对象的run方法。而FutureTask的run方法实际上是调用了Callable的call()方法并将call方法的返回值通过outcome字段记录起来。当通过FutureTask对象的get方法要获取call方法的返回值时会判断FutureTask对象中的状态字段,如果状态为完成则返回,如果状态为未完成则阻塞。所以只要在主线程调用FutureTask的get方法。”主线程运行结束”这段话永远在”Thread-0的call方法结束”则段话之后输出。而如果主线程没有调用FutureTask的get方法,则”主线程运行结束”这段话会在”Thread-0的call方法运行中“之前输出。
- 线程(三)——多线程的实现方式
- C++多线程——三种线程实现方式的区别与实际应用建议
- 多线程——Java多线程实现的三种方式
- 多线程学习总结(三)——实现多线程的方法之线程池
- JAVA多线程之——线程的实现方式
- 多线程之创建线程的方式之一:实现Callable接口(三)
- 多线程之创建线程的方式之一:实现Callable接口(三)
- 多线程-创建线程的三种方式
- 【多线程】创建线程的三种方式
- Java之旅多线程学习(一)——线程的实现方式
- Java多线程——实现线程的方式以及线程的状态
- 09-多线程(创建线程的第二种方式—实现Runnable接口)1 2 10-多线程(第二种方式的细节) 11-多线程(第二种方式的好处)
- 线程池(实现多线程的第三种方式)
- 多线程_02_实现线程的方式
- Java多线程(三)——线程的生命周期
- Java 多线程(三)——线程的生命周期
- Java 多线程(三)——线程的生命周期
- JAVA多线程实现的三种方式
- codeWars之-查找缺少的字母
- MAC上环境变量PATH的几种配置方法
- javascript基础知识点总结
- [杂言] 我,计算机,OI,和我的前 18 年,还有退役
- C++ 指针/引用/常规/CONST型成员的初始化与使用
- 线程(三)——多线程的实现方式
- temp_House
- MAC上安装Mysql数据库、配置环境变量、启动服务、修改密码
- 线段树的坑
- dspic
- gdb基本命令 与 技巧
- Struts2的action 的取值三种方式
- [Leetcode][python]Candy
- Bailian4096 信号转换【密码】