java多线程

多线程

1.1什么是线程

image-20210712094931060

1.2普通方法调用和多线程

.

1.3程序、进程、线程

image-20210712095444327

program:程序,(一个没有执行的程序)

Process:进程,(一个程序执行的过程)

Thread:线程(一个进程能够存在多个线程)

1.4核心

image-20210712100249370

2.1线程的创建

Thread class:继承Thread类

Runable接口:实现Runable接口

Callable接口:实现Callable接口

image-20210712100725565

2.2Thread类

image-20210712103135174

//创建多线程第一个方法:继承Thread类
public class ThreadTest extends Thread{
    //重写run()方法
    //run方法线程体
    @Override
    public void run() {

        for (int i = 0; i < 20; i++) {
            System.out.println("run方法执行"+i);
        }
    }
    //main方法线程体,是默认执行的线程
    public static void main(String[] args) {

        ThreadTest threadTest = new ThreadTest();
        threadTest.start();//调用start方法启动多线程,
//        threadTest.run();//run方法只是启动的方法不是线程
        for (int i = 0; i < 1000; i++) {
            System.out.println("main线程方法执行"+i);
        }
    }
Thread实现网络下载图片
public class ThreadTest1 extends Thread{

        private String url;//图片路径
        private String name;//下载名

    //创建构造器
    public ThreadTest1(String url, String name) {
        this.url = url;
        this.name = name;
    }

    @Override
    public void run() {
        DownLoad downLoad = new DownLoad();
        downLoad.download(url,name);
        System.out.println("下载了文件名为"+name);

    }

    public static void main(String[] args) {
        //创建三个线程
        ThreadTest1 t1 = new ThreadTest1("https://img-blog.csdnimg.cn/img_convert/40f0aea99f5ce22cee00da5fde4c9b18.png", "1.png");
        ThreadTest1 t2 = new ThreadTest1("https://img-blog.csdnimg.cn/img_convert/a3b495a477ed4b140c1412952063e063.png", "2.png");
        ThreadTest1 t3 = new ThreadTest1("https://img-blog.csdnimg.cn/img_convert/85f18c52153fc557f8edda98bd71a491.png", "3.png");
        //同时启动三个线程
        t1.start();
        t2.start();
        t3.start();

    }
}
//创建一个自动下载网上图片的方法
class DownLoad{
    public void download(String url,String name){
        try {
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("download出现问题");
        }
    }
}

image-20210712110805944

2.3实现Runable接口

image-20210712111020211

实现runnable接口与继承Thread类的区别在线程启动是,Runnable线程的启动需要new一个Thread对象作为代理

public class RunnableTest implements Runnable{
    //重写run()方法
    //run方法线程体
    @Override
    public void run() {

        for (int i = 0; i < 20; i++) {
            System.out.println("run方法执行"+i);
        }
    }
    //main方法线程体,是默认执行的线程
    public static void main(String[] args) {

        //创建一个runnabletest对象
        RunnableTest runnableTest = new RunnableTest();
        //创建一个Thread对象,并用start启动这个Thread
        new Thread(runnableTest).start();


        for (int i = 0; i < 1000; i++) {
            System.out.println("main线程方法执行"+i);
        }
    }
}
利用runnable接口实现下载
public class RunnableTest1 implements Runnable{
    private String url;//图片路径
    private String name;//下载名

    //创建构造器
    public RunnableTest1(String url, String name) {
        this.url = url;
        this.name = name;
    }

    @Override
    public void run() {
        DownLoad downLoad = new DownLoad();
        downLoad.download(url,name);
        System.out.println("下载了文件名为"+name);

    }

    public static void main(String[] args) {
        //创建三个线程
        ThreadTest1 t1 = new ThreadTest1("https://img-blog.csdnimg.cn/img_convert/40f0aea99f5ce22cee00da5fde4c9b18.png", "1.png");
        ThreadTest1 t2 = new ThreadTest1("https://img-blog.csdnimg.cn/img_convert/a3b495a477ed4b140c1412952063e063.png", "2.png");
        ThreadTest1 t3 = new ThreadTest1("https://img-blog.csdnimg.cn/img_convert/85f18c52153fc557f8edda98bd71a491.png", "3.png");
        //同时启动三个线程,用thread类代理的模式启动
        new Thread(t1).start();
        new Thread(t2).start();
        new Thread(t3).start();
    }
}
//创建一个自动下载网上图片的方法
class DownLoad1{
    public void download(String url,String name){
        try {
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("download出现问题");
        }
    }
}

2.4Thread类与Runnable接口对比

image-20210712133228217

模拟抢票
//多线程并发展示  抢票机制   多个用户共同抢五十张票
    //问题:多个线程在操作同一个资源的情况下,会出现出票重复问题,线程不安全,数据紊乱
public class RunnableTest2 implements Runnable{


    //定义五十张票
    private int ticketnums=200;
   //重写run方法,多线程执行方法
    @Override
    public void run() {
      //多线程执行体
        while (true){
            if(ticketnums==0){
                //模拟延时
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                break;
            }
            System.out.println(Thread.currentThread().getName()+"抢到了第"+ticketnums--+"张票");
        }
    }

    //main方法体
    public static void main(String[] args) {
      //创建一个要执行的多线程对象
        RunnableTest2 ticket = new RunnableTest2();
        //创建多个Thread对象进行并发测试,多个Thread会同时访问ticket这一个资源
        new Thread(ticket,"黄牛").start();
        new Thread(ticket,"小明").start();
        new Thread(ticket,"小王").start();

    }
}
模拟龟兔赛跑
///龟兔赛跑
public class RaceTest implements Runnable{
    private static String winner;//设置一个存放胜利者的属性
    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {
           //让兔子睡一会
            if(Thread.currentThread().getName()=="兔子"&&i%10==0){
                try {
                    Thread.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            //测试比赛是否结束
            boolean b = gameOver(i);
            //比赛结束后停止
            if(b){
                break;
            }


            System.out.println(Thread.currentThread().getName()+"跑到了第"+i+"步");

        }

    }

    //游戏结束方法
    public boolean gameOver(int race){
        //如果已经有胜利者就返回胜利者
        if (winner!=null){
            //已经有胜利者了
            return true;
        }
        {
            //如果谁先等于一百步,那么胜利者就是谁
            if (race>=100){
                winner=Thread.currentThread().getName();
                System.out.println("winner is"+winner);
                return true;
            }
        }
        return false;
    }

    //main方法
    public static void main(String[] args) {
        //创建线程对象
        RaceTest raceTest = new RaceTest();

        //用两个线程去抢占对象
        new Thread(raceTest,"兔子").start();
        new Thread(raceTest,"乌龟").start();
    }
}

2.5实现Callable接口

image-20210712144325915

Callable的优点
  • 可以定义返回值
  • 可以抛出异常
  • 启动线程的步骤较多
    • 1.创建要执行的线程对象
    • 2.用Executors创建线程池,需要多少个线程就写几
    • 3.将创建的线程提交到线程池执行
    • 4.获得返回结果
    • 5.关闭服务
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值