实现多线程的三种方式

1.继承Thread类

  • 创建一个类集成Thread类
  • 重写run() 方法
  • 调用start() 开启多线程
public class Demo01 extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("这是多线程调用----------");
        }
        //super.run();
    }

    //run()方法是先执行多线程方法,再执行主线程方法。
    //start()方法是开启多线程,主线程和多线程方法交替执行。线程并不是立即执行,由CPU进行调度安排,不可控
    public static void main(String[] args) {
        Demo01 demo01 = new Demo01();
        demo01.start();
        for (int i = 0; i < 2000; i++) {
            System.out.println(i+"这是主线程调用-------");
        }
    }
}

PS:根据个人电脑得配置不同,执行的结果也有可能不同,如果看不出效果,不妨把主线程得执行次数调大。

2.实现Runnable接口

  • 写一个类,实现Runnable接口
  • 重写run() 方法
  • 在执行多线程时需要丢入Runnable接口得实现类
public class Demo03 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("这是线程执行方法-----------");
        }
    }

    public static void main(String[] args) {
        Demo03 demo03 = new Demo03();
        Thread thread = new Thread(demo03);
        thread.start();
        for (int i = 0; i < 200; i++) {
            System.out.println(i+"这是主线程执行的方法----------");
        }
    }
}

小练习:

1.三个人抢500张票

public class SynTest implements Runnable{
    private Integer totalTicket = 500;
    private Boolean flag = true;

    private synchronized void buy(){
        if (totalTicket <= 0){
            flag = false;
            return;
        }
        try {
            Thread.sleep(10);
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"拿到了第"+totalTicket--+"张票");
    }

    public static void main(String[] args) {
        SynTest synTest = new SynTest();
        new Thread(synTest,"小明").start();
        new Thread(synTest,"老师").start();
        new Thread(synTest,"黄牛").start();
    }

    @Override
    public void run() {
        while (flag){
            buy();
        }
    }
}

2.模拟龟兔赛跑

public class Race implements Runnable{
    private static String winner;
    //private Boolean flag;
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            if (Thread.currentThread().getName().equals("兔子") && i%10==0){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            boolean flag = gameOver(i);
            if (flag){
                //System.out.println("胜利者是"+Thread.currentThread().getName());
                break;
            }
            System.out.println(Thread.currentThread().getName()+"---跑了"+i+"步");
        }
    }

    public boolean gameOver(int temp){
        if (winner != null){
            return true;
        }{
            if (temp>=100){
                winner = Thread.currentThread().getName();
                System.out.println("胜利者是"+winner);
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        Race race = new Race();
        new Thread(race,"兔子").start();
        new Thread(race,"乌龟").start();
    }
}

3.实现Callable接口

总体看实现callable与实现runnable接口方式是一样的,区别在于实现callable比实现runnable接口功能更强大,具体表现:

  1. callable可以在任务结束后返回一个值,而runnable不行;

  2. callable可以向外抛出异常,而runnable的run()方法不行;

  3. 可以通过运行Callable得到Fulture对象监听目标线程调用call方法的结果,得到返回值。(fulture.get(),调用后会阻塞,直到获取到返回值

实现步骤:

  1. 创建一个callable接口的子类实例化对象;
  2. 重写call方法,将要在线程中执行的方法写在其中;
  3. 创建ExecutorService线程池;
  4. 将自定义的对象或开启的线程数量放入到线程池里面;
  5. 提交执行;
  6. 获取返回结果;
  7. 关闭线程池,不再接收新的线程,未结束的线程不会停止;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.net.URL;
import java.util.concurrent.*;

/**
 * 实现callable的方式开启多线程
 */
public class Demo01 implements Callable<Boolean> {
    private String url;
    private String name;

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

    @Override
    public Boolean call() throws Exception {
        DownLoadService downLoadService = new DownLoadService();
        downLoadService.down(url,name);
        System.out.println("已经下载了文件名为:"+name);
        return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Demo01 t1 = new Demo01("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201708%2F17%2F20170817165222_uG8XZ.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1619853513&t=b0beb9a2d2d044e227e0ed99002fc1c5", "01.jpg");
        Demo01 t2 = new Demo01("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201708%2F17%2F20170817165222_uG8XZ.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1619853513&t=b0beb9a2d2d044e227e0ed99002fc1c5", "02.jpg");
        Demo01 t3 = new Demo01("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201708%2F17%2F20170817165222_uG8XZ.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1619853513&t=b0beb9a2d2d044e227e0ed99002fc1c5", "03.jpg");

        //创建执行服务
        ExecutorService es = Executors.newFixedThreadPool(3);

        //提交执行
        Future<Boolean> s1 = es.submit(t1);
        Future<Boolean> s2 = es.submit(t2);
        Future<Boolean> s3 = es.submit(t3);

        //获取执行结果
        Boolean b1 = s1.get();
        Boolean b2 = s2.get();
        Boolean b3 = s3.get();
        es.shutdown();
    }
}
class DownLoadService{
    public void down(String url,String name){
        try {
            FileUtils.copyURLToFile(new URL(url),new File(name));
        }catch (Exception e){
            e.printStackTrace();
            System.out.println("down方法抛出异常。");
        }
    }
}

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值