Java——创建线程的三种方式
来源:互联网 发布:windowsce软件 编辑:程序博客网 时间:2024/05/21 17:24
创建线程的三种方式
1. 继承Thread类创建线程类
通过继承Thread类创建并启动多线程的步骤:
1. 定义该类继承Thread,并重写该类的run方法,该run()方法的方法体就代表了线程需要完成的任务。因此run()方法被称为方法执行体。
2. 创建一个Thread子类实例,即创建了线程对象。
3. 调用线程对象的start()方法来启动该进程。
下面的程序是一个示例:
package 多线程;public class MyThread extends Thread { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(getName() + ":" + i); } } public static void main(String[] args) { MyThread my1 = new MyThread(); MyThread my2 = new MyThread(); // 启动线程 my1.start(); my2.start(); }}
可以看见Thread0与Thread1交错出现,并且是不规律的。
上面程序的getName()是进程的名称默认情况下,第一个进程是Thread0,第二个是Thread1…,getName()方法是Thread类的一个实例方法。
我们可以通过setName()来设置线程姓名
,当然setName()也是Thread的实例方法。还可以通过构造器设置线程的名称,如下:
public MyThread () {} public MyThread (String name) { super(name); }
Thread中还有一个静态的方法currentThread(),该方法的作用是返回当前正在执行的线程对象。
package 多线程;public class MyThread extends Thread { public MyThread () {} public MyThread (String name) { super(name); } @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(getName() + ":" + i); } } public static void main(String[] args) { // 通过Thread的currentThread()方法获取当前进程 System.out.println(Thread.currentThread()); MyThread my1 = new MyThread("A"); MyThread my2 = new MyThread("B"); // 启动线程 my1.start(); my2.start(); }}
Thread.currentThread()显示的是main()方法这一条进程,当Java程序启动时,之后会启动一条主进程。
2. 实现Runnable接口创建线程类
实现Runnable接口来创建并启动多线程的步骤如下:
1. 定义一个Runnable接口的实现类,并重写该接口的run()方法,该run()方法就是该线程执行体。
2. 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread才是真正的线程对象。
Thread(Runnable target) 分配新的 Thread 对象
Thread(Runnable target, String name) 分配新的 Thread 对象。
3. 调用线程的start()方法来启动该线程。
下面的一个程序演示了如何启动并创建:
package 多线程;public class RunnableThreadDemo2 implements Runnable{ private int i; @Override public void run() { for ( ; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " : " + i); } } public static void main(String[] args) { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); if (i == 20) { RunnableThreadDemo2 rtd = new RunnableThreadDemo2(); new Thread(rtd, "A").start(); new Thread(rtd, "B").start(); } } }}
可以看到运行的结果,两个子线程的i变量是连续的,也就是采用Runnable接口方式创建的多个线程是可以共享线程类实例变量。这是因为在这种方式下,程序所创建的Runnable对象只是线程的target,而多个线程可以共享一个target,所以多个线程可以共享一个线程类的实例变量。
3. 使用Callable和Future创建线程
Callable是一个有泛型的接口,Callable里定义了一个比run()方法更加强大的call()方法。
1. call()方法可以有返回值:call()方法的返回值即是Callable接口的泛型
2. call()方法可以抛出异常
Java5提供了Future接口代表Callable接口里call()方法的返回值,并为Future接口提供了一个FutureTask实现类,该实现类实现了Future接口,并实现了Runnable接口——可以作为Thread类的target。
boolean cancel(boolean mayInterruptIfRunning)试图取消对此任务的执行。如果任务已完成、或已取消,或者由于某些其他原因而无法取消,则此尝试将失败。当调用 cancel 时,如果调用成功,而此任务尚未启动,则此任务将永不运行。如果任务已经启动,则 mayInterruptIfRunning 参数确定是否应该以试图停止任务的方式来中断执行此任务的线程。
boolean isCancelled()如果在任务正常完成前将其取消,则返回 true。
boolean isDone()如果任务已完成,则返回 true。 可能由于正常终止、异常或取消而完成,在所有这些情况中,此方法都将返回 true。
V get()throws InterruptedException,ExecutionException如有必要,等待计算完成,然后获取其结果
V get(long timeout,TimeUnit unit)throws InterruptedException, ExecutionException,TimeoutException如有必要,最多等待为使计算完成所给定的时间之后,获取其结果(如果结果可用)。
创建并启动有返回值的线程步骤如下:
1. 创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,且该call()方法有返回值。
2. 使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
3. 使用FutureTask对象作为Thread的target创建并启动新线程。
4. 调用FutureTask对象的get方法来获得子线程结束后的返回值。
package 多线程;import java.util.concurrent.Callable;import java.util.concurrent.FutureTask;public class CallableDemo { public static void main(String[] args) { // 创建Callable对象 CallableDemo cd = new CallableDemo(); // 使用Lambda表达式创建Callable<Integer>对象 // 使用FutureTask来包装Callable对象 // Lambda写法// FutureTask<Integer> task = new FutureTask<Integer>((Callable<Integer>)() -> {// int i = 0;// for ( ; i < 100; i++) {// System.out.println(Thread.currentThread().getName() + " : " + i);// }// // call() 方法可以有返回值// return i;// }); FutureTask<Integer> task = new FutureTask<>(new Callable<Integer>() { @Override public Integer call() throws Exception { int i = 0; for ( ; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " : " + i); } // call() 方法可以有返回值 return i; } }); for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " : " + i); if (i == 20) { // 实质还是以Callable对象来启动线程的 new Thread(task, "有返回值得线程").start(); } } try { // 获取线程返回值 System.out.println("子线程的返回值:" + task.get()); } catch (Exception ex) { ex.printStackTrace(); } }}
- Java——创建线程的三种方式
- java创建线程的三种方式
- java创建线程的三种方式
- Java创建线程的三种方式
- Java线程创建的三种方式
- Java创建线程的三种方式
- Java创建线程的三种方式
- Java线程的三种创建方式
- java创建线程的三种方式
- java创建线程的三种方式
- Java创建线程的三种方式
- Java创建线程的三种方式
- java线程(1)——三种创建线程的方式
- Java学习之多线程--创建线程的三种方式
- Java线程——两种创建线程的方式
- java创建线程的三种方式及其对比
- 【java】创建线程的三种方式浅析
- 三种Java创建线程的方式(Callable,FutureTask)
- 加载zip压缩的javascript代码以及在Egret H5实际应用
- 决策树实战项目-鸢尾花分类
- Eclipse查看Servlet源码
- 大神教你设置Linux进程的睡眠和唤醒
- 网络通信之 字节序转换原理与网络字节序、大端和小端模式
- Java——创建线程的三种方式
- hdu 1711 Number Sequence
- command类的使用详解
- 我的线性结构
- spring中bean的生命周期
- 吾爱破解160个crackme之003
- Ajax中POST和GET的区别
- 【转】SAP采购订单屏幕增强
- 【设计模式】JDK源码中用到的设计模式