1、通过实现Runnable接口线程创建

(1).定义一个类实现Runnable接口,重写接口中的run()方法。在run()方法中加入具体的任务代码或处理逻辑。

(2).创建Runnable接口实现类的对象。

(3).创建一个Thread类的对象,需要封装前面Runnable接口实现类的对象。(接口可以实现多继承)

(4).调用Thread对象的start()方法,启动线程

示例代码:

  1. <span style="font-size:16px;">package demo.thread;
  2. public class TreadDemo1 implements Runnable {
  3. private int countDown = 10;
  4. @Override
  5. // 在run方法中定义任务
  6. public void run() {
  7. while (countDown-- > 0) {
  8. System.out.println("#" + Thread.currentThread().getName() + "("
  9. + countDown + ")");
  10. }
  11. }
  12. public static void main(String[] args) {
  13. // Runnable中run方法是一个空方法,并不会产生任何线程行为,必须显式地将一个任务附着到线程上
  14. TreadDemo1 tt=new TreadDemo1();
  15. new Thread(tt).start();
  16. new Thread(tt).start();
  17. System.out.println("火箭发射前倒计时:");
  18. }
  19. }
  20. </span>

运行结果:

火箭发射前倒计时:
#Thread-1(8)
#Thread-1(7)
#Thread-1(6)
#Thread-1(5)
#Thread-1(4)
#Thread-1(3)
#Thread-1(2)
#Thread-1(1)
#Thread-1(0)
#Thread-0(9)

2、通过继承Thread类创建线程

(1).首先定义一个类去继承Thread父类,重写父类中的run()方法。在run()方法中加入具体的任务代码或处理逻辑。
(2).直接创建一个ThreadDemo2类的对象,也可以利用多态性,变量声明为父类的类型。

(3).调用start方法,线程t启动,隐含的调用run()方法。

示例代码:

  1. <span style="font-size:16px;">package demo.thread;
  2. public class ThreadDemo2 extends Thread {
  3. private int countDown = 10;
  4. @Override
  5. // 在run方法中定义任务
  6. public void run() {
  7. while (countDown-- > 0) {
  8. System.out.println("#" + this.getName() + "(" + countDown + ")");
  9. }
  10. }
  11. public static void main(String[] args) {
  12. new ThreadDemo2().start();
  13. new ThreadDemo2().start();
  14. // 由于start方法迅速返回,所以main线程可以执行其他的操作,此时有两个独立的线程在并发运行
  15. System.out.println("火箭发射前倒计时:");
  16. }
  17. }
  18. </span>

运行结果:

#Thread-0(9)
#Thread-0(8)
#Thread-0(7)
#Thread-0(6)
#Thread-0(5)
#Thread-0(4)
#Thread-0(3)
#Thread-0(2)
#Thread-0(1)
#Thread-0(0)
火箭发射前倒计时:
#Thread-1(9)
#Thread-1(8)
#Thread-1(7)
#Thread-1(6)
#Thread-1(5)
#Thread-1(4)
#Thread-1(3)
#Thread-1(2)
#Thread-1(1)
#Thread-1(0)
3、两种方式的比较

首先分析两种方式的输出结果,同样是创建了两个线程,为什么结果不一样呢?

使用实现Runnable接口方式创建线程可以共享同一个目标对象(TreadDemo1 tt=new TreadDemo1();),实现了多个相同线程处理同一份资源。

然后再看一段来自JDK的解释:

Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为run 的无参数方法。

设计该接口的目的是为希望在活动时执行代码的对象提供一个公共协议。例如,Thread 类实现了Runnable。激活的意思是说某个线程已启动并且尚未停止。

此外,Runnable 为非 Thread 子类的类提供了一种激活方式。通过实例化某个Thread 实例并将自身作为运行目标,就可以运行实现
Runnable 的类而无需创建 Thread 的子类。大多数情况下,如果只想重写run() 方法,而不重写其他
Thread 方法,那么应使用 Runnable 接口。这很重要,因为除非程序员打算修改或增强类的基本行为,否则不应为该类创建子类。

采用继承Thread类方式:
(1)优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this,即可获得当前线程。
(2)缺点:因为线程类已经继承了Thread类,所以不能再继承其他的父类。
采用实现Runnable接口方式:
(1)优点:线程类只是实现了Runable接口,还可以继承其他的类。在这种方式下,可以多个线程共享同一个目标对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
(2)缺点:编程稍微复杂,如果需要访问当前线程,必须使用Thread.currentThread()方法。

java多线程总结一:线程的两种创建方式及优劣比较的更多相关文章

  1. java多线程总结:线程的两种创建方式及优劣比较

    1.通过实现Runnable接口线程创建 (1).定义一个类实现Runnable接口,重写接口中的run()方法.在run()方法中加入具体的任务代码或处理逻辑. (2).创建Runnable接口实现 ...

  2. 1.java多线程_实现线程的两种方式

    1.java多线程基本知识 1.1.进程介绍 不管是我们开发的应用程序,还是我们运行的其他的应用程序,都需要先把程序安装在本地的硬盘上.然后找到这个程序的启动文件, 启动程序的时候,其实是电脑把当前的 ...

  3. java多线程总结一:线程的两种创建方式及比较

    1.线程的概念:线程(thread)是指一个任务从头至尾的执行流,线程提供一个运行任务的机制,对于java而言,一个程序中可以并发的执行多个线程,这些线程可以在多处理器系统上同时运行.当程序作为一个应 ...

  4. Thread -线程的两种创建方式

    package cn.learn.thread.Thread; /* 实现Runnable必须重写run()方法,一般推荐用Runnable实现 */ public class RunnableImp ...

  5. [转载]Java线程的两种实现方式

    转载:http://baijiahao.baidu.com/s?id=1602265641578157555&wfr=spider&for=pc 前言 线程是程序的一条执行线索,执行路 ...

  6. 【转载】 Java中String类型的两种创建方式

    本文转载自 https://www.cnblogs.com/fguozhu/articles/2661055.html Java中String是一个特殊的包装类数据有两种创建形式: String s ...

  7. python 多进程的两种创建方式

    Python中使用线程有两种方式:函数或者用类来包装线程对象. 第一种---------函数 菜鸟教程的我没看懂,说说我自己懂的----看视频理解的 import time import thread ...

  8. String变量的两种创建方式

    在java中,有两种创建String类型变量的方式: String str01="abc";//第一种方式 String str02=new String("abc&qu ...

  9. java中多线程的两种创建方式

    一丶继承Thread类实现多线程 第一步:继承Thread类第二步:重写run()方法第三步:创建继承了Thread类的对象 , 调用start()方法启动. //线程创建方式一 : /* 第一步:继 ...

随机推荐

  1. A Tour of Go Methods continued

    In fact, you can define a method on any type you define in your package, not just structs. You canno ...

  2. 转载 ASP.NET Web API 学习

    转载关于ASP.NET Web API 的学习网址 http://www.cnblogs.com/aehyok/p/3432158.html http://www.mashangpiao.net/Ar ...

  3. 编写Qt Designer自定义控件(二)——编写自定义控件界面

    接上文:编写Qt Designer自定义控件(一)——如何创建并使用Qt自定义控件 既然是控件,就应该有界面,默认生成的控件类只是一个继承了QWidget的类,如下: #ifndef LOGLATED ...

  4. Mac OS环境下媒体文件分割工具mediafilesegmenter的简单使用(生成M3U8 TS文件)

    mediafilesegmenter是苹果开发的一款用于分割媒体文件的工具,其功能与mediastreamsegmenter相似,但操作更简单. * 具体可以对比博客中的另一篇简介<Mac OS ...

  5. Java字节码(.class文件)格式详解(一)

    原文链接:http://www.blogjava.net/DLevin/archive/2011/09/05/358033.html 小介:去年在读<深入解析JVM>的时候写的,记得当时还 ...

  6. 虚方法(virtual)和抽象方法(abstract)的区别

    注:本文转载自 http://www.cnblogs.com/michaelxu/archive/2008/04/01/1132633.html 虚方法和抽象方法都可以供派生类重写,它们之间有什么区别 ...

  7. [BZOJ]2132: 圈地计划 最小割

    圈地计划 Description 最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地.据了解,这块土地是一 ...

  8. NSTimer运行机制和线程问题

    A.首先要理解NSTimer运行机制和Runloop之间的关系: 1.IOS的Run Loops机制 Run Loops是线程的基础部份,任何线程,包括主结程,都包含了一个run loop对象,Coc ...

  9. HDU 2112 HDU Today -- from lanshui_Yang

    此题主要是要用到字符串向整数的映射 , 很自然的想到了 STL 中的map ,哎,贡献无数次WA,最后才发现每次运行时 map 忘了清空 !!!!本题,用dijkstra 和 spfa 均可 ,但是要 ...

  10. 函数中的$input

    $input 在此属于一个特殊变量,一般在函数中用于接收输入 function FindWindowsFolder { $input | where-object {$_.Name -eq " ...