JAVA中创建线程的方式有三种,各有优缺点,具体如下:

一、继承Thread类来创建线程

1、创建一个任务类,继承Thread线程类,因为Thread类已经实现了Runnable接口,然后重写run()方法,run()方法中的内容就是需要线程完成的任务。

2、创建一个任务类的对象,即创建了线程对象。

3、调用任务类对象的start()方法,来启动一个线程。

代码实例:

 public class TestThread extends Thread {
public void run() {
for (int i = 0; i < 20; i++) {
// 与Thread.currentThread().getName()相同
System.out.println(this.getName() + " " + i);
}
} public static void main(String[] args) {
TestThread t1 = new TestThread();
TestThread t2 = new TestThread();
t1.start();
t2.start();
}
}

二、实现Runnable接口来创建线程

1、创建一个任务类,实现Runnable接口,并实现run()方法,run()方法中的内容就是需要线程完成的任务。

2、创建一个任务类的对象。

3、任务类必须在线程中执行,因此将任务类的对象作为参数,创建一个Thread类对象,该Thread类对象才是真正的线程对象。

4、调用Thread线程类对象的start()方法,来启动一个线程。

代码实例:

 public class TestThread implements Runnable {
public void run() {
for (int i = 0; i < 20; i++) {
// 获取线程名称,默认格式:Thread-0
System.out.println(Thread.currentThread().getName() + " " + i);
}
} public static void main(String[] args) {
TestThread tt1 = new TestThread();
TestThread tt2 = new TestThread();
// 可为线程添加名称:Thread t1 = new Thread(tt1, "线程1");
Thread t1 = new Thread(tt1);
Thread t2 = new Thread(tt2);
t1.start();
t2.start();
}
}

三、通过Callable和Future来创建线程

1、创建一个任务类,实现Callable接口,并实现call()方法,call()方法中的内容就是需要线程完成的任务,且有返回值。

2、创建一个任务类的对象,并使用FutureTask类来包装任务类的对象,该FutureTask对象封装了任务类对象中call()方法的返回值。

3、任务类必须在线程中执行,因此将FutureTask类的对象作为参数,创建一个Thread类对象,该Thread类对象才是真正的线程对象。

4、调用Thread线程类对象的start()方法,来启动一个线程。

5、调用FutureTask类对象的get()方法来获取线程执行的返回值,即任务类对象中call()方法的返回值。

代码实例:

 public class TestThread implements Callable<Integer> {
public Integer call() {
int i = 0;
for (i = 0; i < 20; i++) {
if (i == 5)
break;
System.out.println(Thread.currentThread().getName() + " " + i);
}
return i;
} public static void main(String[] args) {
TestThread tt = new TestThread();
FutureTask<Integer> ft = new FutureTask<Integer>(tt);
Thread t = new Thread(ft);
t.start();
try {
System.out.println(Thread.currentThread().getName() + " " + ft.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}

四、三种方式创建线程的比较

1、继承Thread类方式:

(1)优点:编写简单,任务类中访问当前线程时,可以直接使用this关键字。

(2)缺点:任务类即线程类已经继承了Thread类,所以不能再继承其他父类。

2、实现Runnable接口的方式:

(1)优点:任务类只实现了Runnable接口,还可以继承其他类。这种方式,可以多个线程对象共享一个任务类对象,即多线程共享一份资源的情况,如下:

     TestThread tt1 = new TestThread();
Thread t1 = new Thread(tt1);
Thread t2 = new Thread(tt1);
t1.start();
t2.start();

(2)缺点:编写稍微复杂,任务类中访问当前线程时,必须使用Thread.currentThread()方法。

3、通过Callable和Future的方式:

(1)优点:任务类只实现了Callable接口,还可以继承其他类,同样多线程下可共享同一份资源,这种方式还有返回值,并且可以抛出返回值的异常。

(2)缺点:编写稍微复杂,任务类中访问当前线程时,必须使用Thread.currentThread()方法。

  总结:在仅仅只重写run()方法,而不重写Thread类其他方法的前提下,比较推荐实现Runnable接口的方式创建线程。因为不打算修改或增强类的基本能力,不应该为其创建子类。而且实现Runnable接口的方式,线程和资源相对分离,程序更加健壮,更符合面向对象的编程思想。当然,需要线程有返回值时可以使用Callable的方式,但Callable的方式有一个问题,当调用get()方法时,如果线程还未执行完毕,则会阻塞到线程执行完毕拿到返回值。

JAVA中创建线程的三种方法及比较的更多相关文章

  1. Java中创建线程的三种方法以及区别

    Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例.Java可以用三种方式来创建线程,如下所示: 1)继承Thread类创建线程 2)实现Runnable接口创建线 ...

  2. Java中创建线程的三种方式以及区别

    在java中如果要创建线程的话,一般有3种方法: 继承Thread类: 实现Runnable接口: 使用Callable和Future创建线程. 1. 继承Thread类 继承Thread类的话,必须 ...

  3. Java中终止线程的三种方法

    终止线程一般建议采用的方法是让线程自行结束,进入Dead(死亡)状态,就是执行完run()方法.即如果想要停止一个线程的执行,就要提供某种方式让线程能够自动结束run()方法的执行.比如设置一个标志来 ...

  4. java中创建线程的几种方法及区别

    1,实现Runnable接口创建线程 特点: A:将代码和数据分开,形成清晰的模型 B:线程体run()方法所在的类可以从其它类中继承一些有用的属性和方法 C:有利于保持程序风格的一致性 2,继承Th ...

  5. java中创建线程的3种方法

    1.继承Thread类优点:可以直接使用Thread类中的方法,代码比较简单.缺点:继承Thread类之后不能继承其他类. 2.实现Runable接口优点:实现接口,比影响继承其他类或实现接口.缺点: ...

  6. Java中创建线程的三种方式及其优缺点

    1.自定义一个继承Thread的类,由于Java的单继承特性,限制了该类的扩展性. 2.实现Runnable接口,重写run()方法. 3.实现Callable接口,重写call方法.线程执行体可以有 ...

  7. java创建线程的三种方法

    这里不会贴代码,只是将创建线程的三种方法做个笼统的介绍,再根据源码添加上自己的分析. 通过三种方法可以创建java线程: 1.继承Thread类. 2.实现Runnable接口. 3.实现Callab ...

  8. 《Java多线程面试题》系列-创建线程的三种方法及其区别

    1. 创建线程的三种方法及其区别 1.1 继承Thread类 首先,定义Thread类的子类并重写run()方法: package com.zwwhnly.springbootaction.javab ...

  9. Java中创建数组的几种方法

    Java中创建数组的几种方法 public static void main(String[] args) { //创建数组的第一种方法 int[] arr=new int[6]; int intVa ...

随机推荐

  1. 数据结构4——浅谈DancingLinks的思想及应用

    在学习DancingLinks之前,我们先来回顾一下我们以前学过的回溯法. 我们学习基础的回溯法的时候,我们都是先判断是否达到解,然后继续搜索. 对于搜到的下一个点,将他标记为使用过( vis[i]= ...

  2. linux搭建SS服务

    基本准备: 购买主机:www.virmach.com LINUX系统操作经验:vim , apt-get 等命令的使用 putty.exe连接ssh工具的使用 开始 使用putty连接上去,并输入密码 ...

  3. MySQL两阶段提交

    参数介绍 innodb_flush_log_at_trx_commit 0: 每隔1s,系统后台线程刷log buffer,也就是把redo日志刷盘,这里会调用fsync,所以可能丢失最后1s的事务. ...

  4. 【转载】netstat--查看服务器[有效]连接数--统计端口并发数--access.log分析

    简介 Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Member ...

  5. es6 的循环

    for-of  循环 for-of 不能直接用来遍历对象的属性,如果你想遍历对象的属性,你可以使用 for-in 语句(for-in 就是用来干这个的),或者使用下面的方式: for (let key ...

  6. Linux下自动化监控内存、存储空间!

    距离上一次更新文章已经过去一段时间了,小编在这段时间因为一些琐事,加上身体生病不能及时更新文章,今天身体逐渐恢复就急忙来更新文章,今天思梦给大家带来的就是如何自动化监控我们的服务器一些基本的配置来保证 ...

  7. List集合及新特性引用

    ArrayList就是动态数组,也是一个对象. 创建一个ArrayList对象,该对象存放在堆内存中,且是一个内存连续的内存区域. 1.ArrayList是用数组实现的,这个数组的内存是连续的,不存在 ...

  8. 【Java学习笔记之二十七】Java8中传多个参数时的方法

    java中传参数时,在类型后面跟"..."的使用:        public static void main(String[] args){       testStringA ...

  9. Codeforces Round #409 (rated, Div. 2, based on VK Cup 2017 Round 2)(A.思维题,B.思维题)

    A. Vicious Keyboard time limit per test:2 seconds memory limit per test:256 megabytes input:standard ...

  10. [51nod1440]迈克打电话

    有n只熊,从1到n进行编号. 第i只熊的电话号码是si.每只熊会给那些电话号码是他的子串的熊打电话(可能会给自己打). call(i, j) 表示第i只熊给第j只熊打电话的次数,也就是第j个串在第i个 ...