原文:http://www.cnblogs.com/skywang12345/p/3479063.html

常见的实现多线程的方式有2种,一是继承Thread类,二是实现 Runnable接口,还可以通过java.util.concurrent包中的线程池来实现多线程。
Thread和Runnable简介
Runnable是一个接口,该接口中只包含了一个run()方法。它的定义如下:

public interface Runnable {
    public abstract void run();
}

可以定义一个类A实现Runnable接口并重写run方法,然后通过new Thread(new A())的方式创建一个线程。
Thread是一个类。Thread本身就实现了Runnable接口。它的声明如下:

public class Thread implements Runnable {

}

Thread和Runnable的不同之处在于
Thread是类,而Runnable是接口;Thread本身是实现了Runnable接口的类。由于一个类只能有一个父类,但是却能实现多个接口,因此实现Runnable接口的方式相比于继承Thread类创建线程的方式具有更好的扩展性。
此外,Runnable还可以用于实现"资源的共享"。即多个线程都基于同一个Runnable对象建立的,它们会共享Runnable对象上的资源。
因此通常通过实现runnable接口实现多线程。

Thread和Runnable的多线程示例
1. Thread的多线程示例

class MyThread extends Thread{
    private int ticket=10;
    public void run(){
        for(int i=0;i<20;i++){
            if(this.ticket>0){
                System.out.println(this.getName()+" 卖票:ticket"+this.ticket--);
            }
        }
    }
}

public class ThreadTest {
    public static void main(String[] args) {
        // 启动3个线程t1,t2,t3;每个线程各卖10张票!
        MyThread t1=new MyThread();
        MyThread t2=new MyThread();
        MyThread t3=new MyThread();
        t1.start();
        t2.start();
        t3.start();
    }
}

运行结果

Thread-0 卖票:ticket10
Thread-1 卖票:ticket10
Thread-2 卖票:ticket10
Thread-1 卖票:ticket9
Thread-0 卖票:ticket9
Thread-1 卖票:ticket8
Thread-2 卖票:ticket9
Thread-1 卖票:ticket7
Thread-0 卖票:ticket8
Thread-1 卖票:ticket6
Thread-2 卖票:ticket8
Thread-1 卖票:ticket5
Thread-0 卖票:ticket7
Thread-1 卖票:ticket4
Thread-2 卖票:ticket7
Thread-1 卖票:ticket3
Thread-0 卖票:ticket6
Thread-1 卖票:ticket2
Thread-2 卖票:ticket6
Thread-2 卖票:ticket5
Thread-2 卖票:ticket4
Thread-1 卖票:ticket1
Thread-0 卖票:ticket5
Thread-2 卖票:ticket3
Thread-0 卖票:ticket4
Thread-2 卖票:ticket2
Thread-0 卖票:ticket3
Thread-2 卖票:ticket1
Thread-0 卖票:ticket2
Thread-0 卖票:ticket1

结果说明
(01) MyThread继承于Thread,它是自定义个线程。每个MyThread都会卖出10张票。
(02) 主线程main创建并启动3个MyThread子线程。每个子线程都各自卖出了10张票。

2. Runnable的多线程示例

class MyThread implements Runnable{
    private int ticket=10;
    public void run(){
        for(int i=0;i<20;i++){
            if(this.ticket>0){
                System.out.println(Thread.currentThread().getName()+" 卖票:ticket"+this.ticket--);
            }
        }
    }
}

public class RunnableTest {
    public static void main(String[] args) {
        MyThread mt=new MyThread();

        // 启动3个线程t1,t2,t3(它们共用一个Runnable对象),这3个线程一共卖10张票!
        Thread t1=new Thread(mt);
        Thread t2=new Thread(mt);
        Thread t3=new Thread(mt);
        t1.start();
        t2.start();
        t3.start();
    }
}

运行结果

Thread-0 卖票:ticket10
Thread-2 卖票:ticket8
Thread-1 卖票:ticket9
Thread-2 卖票:ticket6
Thread-0 卖票:ticket7
Thread-2 卖票:ticket4
Thread-1 卖票:ticket5
Thread-2 卖票:ticket2
Thread-0 卖票:ticket3
Thread-1 卖票:ticket1

结果说明
(01) 和上面"MyThread继承于Thread"不同;这里的MyThread实现了Thread接口。
(02) 主线程main创建并启动3个子线程,而且这3个子线程都是基于"mt这个Runnable对象"而创建的。运行结果是这3个子线程一共卖出了10张票。这说明它们是共享了MyThread接口的。

实际上这个程序卖出的票有很能不止十张,问题出在多线程对ticket这个竞争资源的互斥访问上,下面是一种解决方法。

class MyThread implements Runnable{
    private volatile int ticket=10;
    public synchronized void run(){
        for(int i=0;i<20;i++){
            if(this.ticket>0){
                System.out.println(Thread.currentThread().getName()+" 卖票:ticket"+this.ticket--);
            }
        }
    }
}

Java多线程2:实现多线程的两种方式的更多相关文章

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

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

  2. 遍历Map集合:java.util.Map.Entry、KeySet两种方式

    遍历Map集合的两种方式: 1.用KeySet Map.keySet(),返回一个存放所有key的set集合,通过遍历集合,根据key值取出所有的value值. Map<String,Strin ...

  3. Java并发--线程间协作的两种方式:wait、notify、notifyAll和Condition

    在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界 ...

  4. java文件末尾追加内容的两种方式

    java 开发中,偶尔会遇到在文件末尾对文件内容进行追加,实际上有多种方式可以实现,简单介绍两种: 一种是通过RandomAccessFile类实现,另一种是通过FileWriter类来实现. 实现方 ...

  5. Java中 单例(Singleton)的两种方式

    第一种(饿汉式单例模式):在声明变量时实例化 public class Singleton { //静态初始化自动实例化 private static Singleton instance = new ...

  6. Java字符流读写数据的两种方式

    第一种方式:逐个字符进行读写操作(代码注释以及详细内容空闲补充) package IODemo; import java.io.FileReader; import java.io.FileWrite ...

  7. java发送http get请求的两种方式

    长话短说,废话不说 一.第一种方式,通过HttpClient方式,代码如下: public static String httpGet(String url, String charset) thro ...

  8. Java代码模拟http请求的两种方式

    z这里用百度地图的逆地理编码接口为例, 第一种方式:(通过jdk中的java.net包) 引入工具类 import java.net.URL; import java.net.URLConnectio ...

  9. JAVA·多线程:创建线程的两种方式

    1.–扩展java.lang.Thread类 package multiThread; public class Thread02extThread { public static void main ...

  10. java制作二维码的两种方式

    原博:http://www.importnew.com/15028.html Zebra Crossing(ZXing)是一个很棒的,几乎可以在所有平台(Android.JavaSE.iPhone.R ...

随机推荐

  1. 错误信息:未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序。

    下载2007 Office system 驱动程序:数据连接组件安装 http://download.microsoft.com/download/7/0/3/703ffbcb-dc0c-4e19-b ...

  2. Delphi XE5教程1:语言概述

    内容源自Delphi XE5 UPDATE 2官方帮助<Delphi Reference>,本人水平有限,欢迎各位高人修正相关错误! 也欢迎各位加入到Delphi学习资料汉化中来,有兴趣者 ...

  3. django post报403问题

    第一个问题是: 我使用jquery的ajax向后台传值, 当使用GET方法时没问题 $.ajax({ type:"GET" url: data: success: }) 但是由于基 ...

  4. mac常用设置

    1.修改mac主机名 系统偏好设置->共享->电脑名称 ,编辑就可以了. sudo scutil --set HostName hostname 这个是修改主机名 sudo scutil ...

  5. vs2012用wpf制作透明窗口中报错的解决方案

    在开发wpf项目时,需要调用外部com组件,同时需要制作透明窗口,于是问题出现了,当我们在设置 AllowsTransparency="True"后,com组件显示不出来了,只有透 ...

  6. UML 小结(2)- 理论理解

    什么是UML: UML是统一建模语言(UML是 Unified Modeling Language的缩写)是用来对软件密集系统进行可视化建模的一种语言. UML为面向对象开发系统的产品进行说明.可视化 ...

  7. 浅析JVM内存结构和6大区域(转)

    其实对于我们一般理解的计算机内存,它算是CPU与计算机打交道最频繁的区域,所有数据都是先经过硬盘至内存,然后由CPU再从内存中获取数据进行处理,又将数据保存到内存,通过分页或分片技术将内存中的数据再f ...

  8. Google history

    传说,硅谷的公司在和微软的竞争中一直处于下风,不论在市场,人才,还是在打官司上,直到婴儿巨人Baby Giant谷歌的出现,历史才出现前所未有的改变.Google以一个强大的挑战者的身份出现在人们的视 ...

  9. 【BZOJ】【2588】COT(Count On a Tree)

    可持久化线段树 maya……树么……转化成序列……所以就写了个树链剖分……然后每个点保存的是从它到根的可持久化线段树. 然后就像序列一样查询……注意是多个左端点和多个右端点,处理方法类似BZOJ 19 ...

  10. MSAA

    多重采样抗锯齿(MultiSampling Anti-Aliasing,簡稱MSAA)是一种特殊的超级采样抗锯齿(SSAA).MSAA首先来自于OpenGL.具体是MSAA只对Z缓存(Z-Buffer ...