Java中的多线程如何实现?

Java中的多线程如何实现?

先来简单说一下,什么是多线程,举个很简单的例子,我们生活中一个人可以同时做几件事,这就是多线程啊,对应Java中的多线程也是这样,我们以前main方法中执行,其实我们java中还有一个守护进程gc垃圾回收,这个以后再说。一个进程中有很多个线程,这些线程可以同时执行,进程就相当于一个保护的角色,这些概念性的东西可以去百度百科看,这里就不多介绍了。主要还是看看如何实现多线程。主要有三种方法:

1.继承Thread类

继承这个类,我们需要重写run()方法,然后开启线程用start()方法,这个时候我们再来一个main()方法,就可以看出来,这两个线程是同时的,交替进行:

public class Thread01 extends Thread {

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("我是run---"+i);
        }
    }

    public static void main(String[] args) {

        Thread01 th = new Thread01();
        th.start();

        for (int i = 0; i < 1000; i++) {
            System.out.println("我是main"+i);
        }
    }
}

举个下载图片的例子吧:

pom.xml

 <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
 </dependency>

下载的工具类:

public class DownloadUtils {

    public void webdownload(String url , String name){
        try {
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

主类:

public class PictureDowload extends Thread {

    private String url;
    private String name;

    public PictureDowload(String url, String name) {
        this.url = url;
        this.name = name;
    }

    @Override
    public void run() {
        DownloadUtils du = new DownloadUtils();
        du.webdownload(url,name);
    }

    public static void main(String[] args) {
        PictureDowload p1 = new PictureDowload("https://ns-strategy.cdn.bcebos.com/ns-strategy/upload/fc_big_pic/part-00264-919.jpg", "1.jpg");
        PictureDowload p2 = new PictureDowload("https://ns-strategy.cdn.bcebos.com/ns-strategy/upload/fc_big_pic/part-00049-3015.jpg", "2.jpg");
        PictureDowload p3 = new PictureDowload("https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=2683403104,2904190188&fm=26&gp=0.jpg", "3.jpg");


        p1.start();
        p2.start();
        p3.start();
    }
}

2.实现Runnable接口

这个方法也是要重写run()方法,不过启动线程的方法有点不同,需要用Thrad来代理Runnable 接口的实现类对象。这个是为什么呢?其实啊,第一种方法中没有介绍,Thread也是实现了Runnable接口的,如下:

class Thread implements Runnable {
    /* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
        registerNatives();
    }

上面是Thread一部分源码而已,不过可以看出来也是实现了Runnable接口的

那么还是上面那个例子,我们 只需要改进一点点就可以启动多线程下载图片了,如下:

public class PictureDowload01 implements Runnable {

    private String url;//网络图片路径
    private String name;//下载后所取得文件名

    public PictureDowload01(String url, String name) {
        this.url = url;
        this.name = name;
    }

    @Override
    public void run() {
        DownloadUtils du = new DownloadUtils();
        du.webdownloadpicture(url,name);
    }

    public static void main(String[] args) {
        PictureDowload01 p1 = new PictureDowload01("https://ns-strategy.cdn.bcebos.com/ns-strategy/upload/fc_big_pic/part-00264-919.jpg", "1.jpg");
        PictureDowload01 p2 = new PictureDowload01("https://ns-strategy.cdn.bcebos.com/ns-strategy/upload/fc_big_pic/part-00049-3015.jpg", "2.jpg");
        PictureDowload01 p3 = new PictureDowload01("https://ns-strategy.cdn.bcebos.com/ns-strategy/upload/fc_big_pic/part-00423-3960.jpg", "3.jpg");

        new Thread(p1).start();
        new Thread(p2).start();
        new Thread(p3).start();

    }
}

是不是觉得很简单了啊,就是启动需要借助Thread而已,其余的一样,没什么复杂的。

那么既然有两种方法,我们怎么选择是不是一个问题,并不是随便来用的啊,下面我们来分析一下:、

  • 继承Thread方法的局限性,是能单继承,一个对象不能实现被多个线程使用,是不是局限性很大啊,所以这里我不推荐大家用这种方法

  • 实现Runnable接口的方法,突破了上面的局限性,一个对象可以被多个线程使用,很方便,我比较推荐这种写法,举个例子:

    //一份资源
    ThreadTest th = new ThreadTest();
    
    //多个代理
    new Thread(th,"m1").start();
    new Thread(th,"m2").start();
    new Thread(th,"m3").start();
    

    是不是突然觉得好方便,突破了单继承的局限性,对不对

举个现实中的例子,来讲解一下这个(首先这个例子没有解决并发问题,这里只是单纯演示这个而已)

public class SoldTicket implements Runnable {

    int ticketnum = 15;//票数


    @Override
    public void run() {
        while (true){
            if (ticketnum <= 0){
                break;
            }

            System.out.println(Thread.currentThread().getName()+"买到了第" + ticketnum-- +"票");
        }
    }

    public static void main(String[] args) {
        SoldTicket st = new SoldTicket();
        new Thread(st,"张三").start();
        new Thread(st,"李四").start();
        new Thread(st,"王五").start();
    }
}


3.实现Callable接口

这种方法用的比较少具体使用我就不举例子了,就是实现Callable 接口,重写call方法,然后就是开启线程有点不一样,需要先开启服务,结束后还要关闭服务。其实这种开启多线程用的还是比较少,起码我用的很少,这里就不去举例子了,如果真的要用到,我们随时百度查一下用法,也是很贱的,没什么复杂的,重点掌握前两种方法,就足够使用了,推荐使用的是第二种

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值