java中实现多线程

JAVA多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。在这里我们主要说明前两中方式。

1.继承Thread类实现多线程

Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过Thread类的start()实例方法。start()方法是一个native方法,它将启动一个新线程,并执行run()方法。这种方式实现多线程很简单,通过自己的类直接extend Thread,并复写run()方法,就可以启动新线程并执行自己定义的run()方法。

一个简单的实例

public class MyThread extends Thread {
    private String name;

    public MyThread(String name) {
        this.name = name;
    }
    public void run() {  
        for (int i = 0; i < 5; i++) {
            System.out.println(name + "运行 : " + i);
        }  
    }  

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        MyThread t1=new MyThread("A");
        MyThread t2=new MyThread("B");
        t1.start();
        t2.start();
    }
}

运行结果
可能是: 也可能是:
这里写图片描述 这里写图片描述

因为需要用到CPU的资源,所以每次的运行结果基本是都不一样的。虽然我们在这里调用的是start()方法,但是实际上调用的还是run()方法的主体。

2.通过实现Runnable接口

如果自己的类已经extends另一个类,就无法直接extends Thread,此时,必须实现一个Runnable接口。
先看一个实例

public class MyThread implements Runnable {
    private String name;

    public MyThread(String name) {
        this.name = name;
    }
    public void run() {  
        for (int i = 0; i < 5; i++) {
            System.out.println(name + "运行 : " + i);
        }  
    }  

    public static void main(String[] args) {
        MyThread t1=new MyThread("线程A");
        Thread demo1= new Thread(t1);
        MyThread t2=new MyThread("线程B");
        Thread demo2=new Thread(t2);
        demo1.start();
        demo2.start();
    }
}

运行结果:
这里写图片描述 这里写图片描述

为了启动MyThread,需要首先实例化一个Thread,并传入自己的MyThread实例。

其实Thread中的run方法调用的是Runnable接口的run方法。不知道大家发现没有,Thread和Runnable都实现了run方法,这种操作模式其实就是代理模式。

class Thread implements Runnable {

public void run() {
        if (target != null) {
             target.run();
        }
        }
}

3.Thread和Runnable的区别

如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。

继承Thread类

public class MyThread extends Thread {
    private int ticket = 4;

    public void run() {
        for (int i = 0; i < 5; i++) {
            if (ticket > 0) {
                System.out.println("车票还有 " + ticket-- +"张");
            }
        }
    } 

    public static void main(String[] args) {
        MyThread h1 = new MyThread();
        MyThread h2 = new MyThread();
        MyThread h3 = new MyThread();
        h1.start();
        h2.start();
        h3.start();
    }
}

运行结果:
这里写图片描述

这里并没有实现资源的共享,我们换为Runnable接口

public class MyThread implements Runnable {
    private int ticket = 4;

    public void run() {
        for (int i=0; i<=20; i++) {
            if (this.ticket > 0) {
                System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--);
            }
        }
    }

    public static void main(String[] args) {
        MyThread my = new MyThread();
        new Thread(my, "1号窗口").start();
        new Thread(my, "2号窗口").start();
        new Thread(my, "3号窗口").start();
    }
}

运行结果:
这里写图片描述

实现Runnable接口比继承Thread类所具有的优势:

1):适合多个相同的程序代码的线程去处理同一个资源

2):可以避免java中的单继承的限制

3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。

在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM实习在就是在操作系统中启动了一个进程。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值