Java中实现多线程有两种方法:继承Thread类、实现Runnable接口,在程序开发中只要是多线程,肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下优势:

1、可以避免由于Java的单继承特性而带来的局限;

2、增强程序的健壮性,代码能够被多个线程共享,代码与数据是独立的;

3、适合多个相同程序代码的线程区处理同一资源的情况。

下面以典型的买票程序(基本都是以这个为例子)为例,来说明二者的区别。

首先通过继承Thread类实现,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class MyThread extends Thread{
    private int ticket = 5;
    public void run(){
        for (int i=0;i<10;i++)
        {
            if(ticket > 0){
                System.out.println("ticket = " + ticket--);
            }
        }
    }
}
public class ThreadDemo{
    public static void main(String[] args){
        new MyThread().start();
        new MyThread().start();
        new MyThread().start();
    }
}

某次的执行结果如下:

从结果中可以看出,每个线程单独卖了5张票,即独立地完成了买票的任务,但实际应用中,比如火车站售票,需要多个线程去共同完成任务,在本例中,即多个线程共同买5张票。

下面是通过实现Runnable接口实现的多线程程序,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class MyThread implements Runnable{
    private int ticket = 5;
    public void run(){
        for (int i=0;i<10;i++)
        {
            if(ticket > 0){
                System.out.println("ticket = " + ticket--);
            }
        }
    }
}
public class RunnableDemo{
    public static void main(String[] args){
        MyThread my = new MyThread();
        new Thread(my).start();
        new Thread(my).start();
        new Thread(my).start();
    }
}

某次的执行结果如下:

从结果中可以看出,三个线程一共卖了5张票,即它们共同完成了买票的任务,实现了资源的共享。

针对以上代码补充三点:

1、在第二种方法(Runnable)中,ticket输出的顺序并不是54321,这是因为线程执行的时机难以预测,ticket–并不是原子操作。

2、在第一种方法中,我们new了3个Thread对象,即三个线程分别执行三个对象中的代码,因此便是三个线程去独立地完成卖票的任务;而在第二种方法中,我们同样也new了3个Thread对象,但只有一个Runnable对象,3个Thread对象共享这个Runnable对象中的代码,因此,便会出现3个线程共同完成卖票任务的结果。如果我们new出3个Runnable对象,作为参数分别传入3个Thread对象中,那么3个线程便会独立执行各自Runnable对象中的代码,即3个线程各自卖5张票。

3、在第二种方法中,由于3个Thread对象共同执行一个Runnable对象中的代码,因此可能会造成线程的不安全,比如可能ticket会输出-1(如果我们System.out….语句前加上线程休眠操作,该情况将很有可能出现),这种情况的出现是由于,一个线程在判断ticket为1>0后,还没有来得及减1,另一个线程已经将ticket减1,变为了0,那么接下来之前的线程再将ticket减1,便得到了-1。这就需要加入同步操作(即互斥锁),确保同一时刻只有一个线程在执行每次for循环中的操作。而在第一种方法中,并不需要加入同步操作,因为每个线程执行自己Thread对象中的代码,不存在多个线程共同执行同一个方法的情况。

from: http://www.importnew.com/20584.html

原文出处: 兰亭风雨

Java并发编程(6):Runnable和Thread实现多线程的区别(含代码)相关推荐

  1. Java 并发编程系列之带你了解多线程

    早期的计算机不包含操作系统,它们从头到尾执行一个程序,这个程序可以访问计算机中的所有资源.在这种情况下,每次都只能运行一个程序,对于昂贵的计算机资源来说是一种严重的浪费. 操作系统出现后,计算机可以运 ...

  2. 【Java并发编程】:Runnable和Thread实现多线程的区别

    Java中实现多线程有两种方法:继承Thread类.实现Runnable接口,在程序开发中只要是多线程,肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下 ...

  3. Java并发编程(一)Thread详解

    一.概述 在开始学习Thread之前,我们先来了解一下 线程和进程之间的关系: 线程(Thread)是进程的一个实体,是CPU调度和分派的基本单位. 线程不能够独立执行,必须依存在应用程序中,由应用程 ...

  4. Java并发编程—说说Runnable与Callable

    原文作者:每天一点 原文地址:说说Runnable与Callable 首先,我们先看看使用Callable创建线程与使用Runable的区别: import java.util.concurrent. ...

  5. Java并发编程举例Runnable, Callable, Future, FutureTask, CompletionService

    import java.util.concurrent.*;/*** Created by chenh on 2017/3/23.*/ public class ConcurrentDemo {// ...

  6. Java并发编程(三)volatile域

    相关文章 Java并发编程(一)线程定义.状态和属性 Java并发编程(二)同步 Android多线程(一)线程池 Android多线程(二)AsyncTask源代码分析 前言 有时仅仅为了读写一个或 ...

  7. Java并发编程:Thread类的使用

    为什么80%的码农都做不了架构师?>>>    Java并发编程:Thread类的使用 在前面2篇文章分别讲到了线程和进程的由来.以及如何在Java中怎么创建线程和进程.今天我们来学 ...

  8. Java并发编程71道面试题及答案

    Java并发编程71道面试题及答案 1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任何线程都可以设置为守护线程和用户线程,通过方 ...

  9. Java并发编程有多难?这几个核心技术你掌握了吗?

    本文主要内容索引 1.Java线程 2.线程模型 3.Java线程池 4.Future(各种Future) 5.Fork/Join框架 6.volatile 7.CAS(原子操作) 8.AQS(并发同 ...

最新文章

  1. Apache htaccess 重写假设文件存在!
  2. 0603贴片电阻阻值对照表_怎样读贴片电阻阻值
  3. php中 elseif和else if 的区别
  4. HTML5 的知识分享(二):HTML5 的常用标签
  5. leetcode 108. Convert Sorted Array to Binary Search Tree | 108. 将有序数组转换为二叉搜索树(Java)
  6. Nignx出现failed (3: The system cannot find the path specified)问题
  7. deepin终端启动自安装程序
  8. 【NOIP2017】【Luogu3955】图书管理员(枚举,取模得后缀)
  9. Oracle DB优化-如何看SQL的执行计划+收集表的统计信息
  10. 动态心电图信息存储(三)
  11. 仓库管理无纸化,WMS仓库管理软件+条形码技术
  12. 专网网速测试软件,CMD怎么测试网速?测网速用命令PING
  13. lfs库下载_lua使用lfs.dll库进行文件操作
  14. win7系统如何提升电脑开机速度?
  15. phpcms V9 模板使用 模板安装 模板怎么用?
  16. 成为一个大数据开发工程师的学习步骤--文字版
  17. 【高德地图API】从头德国高中生JS API(三)覆盖物——大喊|折线|多边形|信息表|聚合marker|点蚀图|照片覆盖...
  18. 汇编-ASCⅡ码转二进制码
  19. 美肤宝母公司环亚冲刺深交所:年营收超20亿 为胡兴国家族企业
  20. 【高危】Google Chrome V8 类型混淆漏洞(CVE-2023-2033)

热门文章

  1. elasticsearch6.X 及head插件部署(完整版)
  2. CSDN蒋涛大数据表明:DCO - 区块链时代企业级服务的全新机会
  3. LSTM入门必读:从入门基础到工作方式详解 By 机器之心2017年7月24日 12:57 长短期记忆(LSTM)是一种非常重要的神经网络技术,其在语音识别和自然语言处理等许多领域都得到了广泛的应用
  4. GMIS 2017大会Saman Farid演讲:人工智能时代创业者面对的挑战和机会
  5. 李彦宏:人工智能不是零和游戏
  6. html中after伪类原理,css伪类before跟after原理与使用(原)
  7. RocketMQ:Consumer概述及启动流程与消息拉取源码分析
  8. jsp springmvc 视图解析器_Springmvc中多视图解析器解析问题
  9. 数据结构与算法笔记(六)—— 冒泡排序
  10. 学习笔记——os模块常见列表