本文转载自:http://www.linuxidc.com/Linux/2013-12/93690.htm#0-tsina-1-14812-397232819ff9a47a7b7e80a40613cfe1

  

  Java中有两种实现多线程的方式。一是直接继承Thread类,二是实现Runnable接口。那么这两种实现多线程的方式在应用上有什么区别呢?

  为了回答这个问题,我们可以通过编写一段代码来进行分析。我们用代码来模拟铁路售票系统,实现通过四个售票点发售某日某次列车的100张车票,一个售票点用一个线程表示。

  我们首先这样编写这个程序:

public class ThreadDome1{

  public static void main(String[] args){

    ThreadTest t = new ThreadTest();
t.start();
t.start();
t.start();
t.start();
} }

class ThreadTest extends Thread{ private int ticket = 100; public void run(){
while(true){
if(ticket > 0){
System.out.println(Thread.currentThread().getName() +
"is saling ticket" + ticket--);
}else{
break;
}
}
}
}

  上面的代码中,我们用ThreadTest类模拟售票处的售票过程,run方法中的每一次循环都将总票数减1,模拟卖出一张车票,同时该车票号打印出来,直接剩余的票数到零为止。在ThreadDemo1类的main方法中,我们创建了一个线程对象,并重复启动四次,希望通过这种方式产生四个线程。从运行的结果来看我们发现其实只有一个线程在运行,这个结果告诉我们:一个线程对象只能启动一个线程,无论你调用多少遍start()方法,结果只有一个线程。

我们接着修改ThreadDemo1,在main方法中创建四个Thread对象:

public class ThreadDemo1{

  public static void main(String[] args){

    new ThreadTest().start();
new ThreadTest().start();
new ThreadTest().start();
new ThreadTest().start();
}
} class ThreadTest extends Thread{ private int ticket = 100; public void run(){
while(true){
if(ticket > 0){
System.out.println(Thread.currentThread().getName() +
" is saling ticket" + ticket--);
}else{
break;
}
}
}
}

这下达到目的了吗?

从结果上看每个票号都被打印了四次,即四个线程各自卖各自的100张票,而不去卖共同的100张票。这种情况是怎么造成的呢?我们需要的是,多个线程去处理同一个资源,一个资源只能对应一个对象,在上面的程序中,我们创建了四个ThreadTest对象,就等于创建了四个资源,每个资源都有100张票,每个线程都在独自处理各自的资源。

经过这些实验和分析,可以总结出,要实现这个铁路售票程序,我们只能创建一个资源对象,但要创建多个线程去处理同一个资源对象,并且每个线程上所运行的是相同的程序代码。在回顾一下使用接口编写多线程的过程。

public class ThreadDemo1{

  public static void main(String[] args){

    ThreadTest t = new ThreadTest();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start(); } } class ThreadTest implements Runnable{ private int tickets = 100; public void run(){
while(true){
if(tickets > 0){
System.out.println(Thread.currentThread().getName() +
" is saling ticket " + tickets--);
} else {
      break;
    }
}
}
}

  上面的程序中,创建了四个线程,每个线程调用的是同一个ThreadTest对象中的run()方法,访问的是同一个对象中的变量(tickets)的实例,这个程序满足了我们的需求。在Windows上可以启动多个记事本程序一样,也就是多个进程使用同一个记事本程序代码。

  可见,实现Runnable接口相对于继承Thread类来说,有如下显著的好处:

  (1)适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码,数据有效的分离,较好地体现了面向对象的设计思想。

  (2)可以避免由于Java的单继承特性带来的局限。我们经常碰到这样一种情况,即当我们要将已经继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么,这个类就只能采用实现Runnable接口的方式了。

  (3)有利于程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。当多个线程的执行代码来自同一个类的实例时,即称它们共享相同的代码。多个线程操作相同的数据,与它们的代码无关。当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去,这个对象就是一个实现了Runnable接口的类的实例。

Java中两种实现多线程方式的对比分析的更多相关文章

  1. Java中有两种实现多线程的方式以及两种方式之间的区别

    看到一个面试题.问两种实现多线程的方法.没事去网上找了找答案. 网上流传很广的是一个网上售票系统讲解.转发过来.已经不知道原文到底是出自哪里了. Java中有两种实现多线程的方式.一是直接继承Thre ...

  2. mybatis中两种取值方式?谈谈Spring框架理解?

    1.mybatis中两种取值方式? 回答:Mybatis中取值方式有几种?各自区别是什么? Mybatis取值方式就是说在Mapper文件中获取service传过来的值的方法,总共有两种方式,通过 $ ...

  3. JAVA 中两种判断输入的是否是数字的方法__正则化_

    JAVA 中两种判断输入的是否是数字的方法 package t0806; import java.io.*; import java.util.regex.*; public class zhengz ...

  4. java中两种类型变量

    Java中有两种类型的变量,一种是对象类型,另一种是基础类型(primitive type). 对象类型普遍采用引用的方式,比如 List a = new ArrayList(); List b = ...

  5. JSON语言规范与Java中两种解析工具基本使用

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6652250.html  一:JSON语言规范 一言以蔽之:“一个 :一个键值对,一个{}一个对象,一个[]一个 ...

  6. Spring中两种引入配置文件方式

    用过Spring的人都知道,我们一般把数据库的配置.日志的配置或者其他的通用配置放在单独的配置文件中,在和Spring整合时,一般通过以下两种方法引入: <context:property-pl ...

  7. Java中9种常见的CMS GC问题分析与解决

    1. 写在前面 | 本文主要针对 Hotspot VM 中"CMS + ParNew"组合的一些使用场景进行总结.重点通过部分源码对根因进行分析以及对排查方法进行总结,排查过程会省 ...

  8. java中三种for循环之间的对比

    普通for循环语法: for (int i = 0; i < integers.length; i++) { System.out.println(intergers[i]); } foreac ...

  9. C#中几种创建对象的方式的对比

    最近学习了msil,发现了很多好玩的,今天介绍一个用IL来创建对象的方式 1.最常见的两种创建对象方式 public static T Create<T>() where T : new( ...

随机推荐

  1. 面试前的准备---C#知识点回顾----01

    过完年来,准备找份新工作,虽然手里的工作不错,但树挪死,人挪活.咱不能一直在一个坑里生活一辈子,外面的世界毕竟是很美好的. 为了能正常的找到自己中意的工作,最近是将所有的基础知识拿出来复习了一次.仅作 ...

  2. MVC不错的学习资料

    MVC不错的学习资料: http://www.cnblogs.com/darrenji/

  3. OCMOCM

    14年,OCM考试费12000 15年,考试费19800 对于我来说,1,2年之后是否换工作还是个未知数 在本单位考这个貌似没什么用处,工资也不会突然就涨很多 跳槽的话,专门做数据库感觉压力还挺大 年 ...

  4. (重要) html概念之 input:name与id详解

    实例: 带有两个文本字段和一个提交按钮的 HTML 表单: <form action="form_action.asp" method="get"> ...

  5. section 模块页面切换代码

    <div class="blockcode"><blockquote><!DOCTYPE html><html><head&g ...

  6. jquery学习之笔记一

    jquery是继prototype后一个很好用的javascript库.jquery是一个轻量级的库,拥有强大的选择器,出色的DOM操作,可靠的事件处理,完善的兼容性和链式操作等功能. window. ...

  7. Android studio GPU Monitor :GPU Profiling needs to be enabled in the device's developer options

    Android studio GPU Monitor 在真机上不能使用,提示:GPU Profiling needs to be enabled in the device's developer o ...

  8. WinCe 如何使应用程序只开启一个

    方法一: namespace MyNameSpace{ static class Program { [DllImport("Toolhelp.dll")] public stat ...

  9. FTP配置参数

    格式 vsftpd.conf 的格式非常简单,每行要么是一个注释,要么是一个指令.注释行以#开始并被忽略掉.指令行格式如下: 配置项=参数值 很重要的一点是,这个格式里不存在任何空格. 默认的,每一个 ...

  10. JSONP(转)

    1.一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面.动态网页.web服务.WCF,只要是跨域请求,一律不准: 2.不过我们又发现,Web页面上调用js文件时则不 ...