线程、多线程、线程的三种创建方法

多线程

线程简介

◆线程就是独立的执行路径;

◆在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程;

◆main()称之为主线程,为系统的入口,用于执行整个程序;

◆在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能认为的干预的。

◆对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制;

◆线程会带来额外的开销,如cpu调度时间,并发控制开销。

◆每个线程在自己的工作内存交互,内存控制不当会造成数据不一致

线程的创建

继承Thread类(重点)

package com.cjp;
    
    public class MyThread1 extends Thread{
        @Override
        public void run() {
            //run方法线程体
            for (int i = 0; i < 20; i++) {
                System.out.println("子线程"+i);
            }
        }
    
        public static void main(String[] args) {
            //主线程
            //创建一个线程对象
            MyThread1 t = new MyThread1();
            t.start(); //调用start()方法开启子线程
            
            for (int i = 0; i < 20; i++) {
                System.out.println("主线程"+i);
            }
        }
    }
    //运行结果是 两个线程无规律交替执行
    //注意:线程开启不一定立即执行,由cpu调度执行
  • 多线程下载网图
 package com.cjp;
    
    import org.apache.commons.io.FileUtils;
    
    import java.io.File;
    import java.io.IOException;
    import java.net.URL;
    
    public class MyThread2 extends Thread{
        private String url;
        private String name;
    
        public MyThread2(String url,String name) {
            this.url = url;
            this.name = name;
        }
    
        @Override
        //下载图片线程的线程体
        public void run() {
            WebDownloader w = new WebDownloader();
            w.downloader(url,name);
            System.out.println("下载了文件名为:"+name);
        }
    
    
        public static void main(String[] args) {
            MyThread2 t1 = new MyThread2("图片链接","1.jpg");
     MyThread2 t2 = new MyThread2("图片链接","2.jpg");
     MyThread2 t3 = new MyThread2("图片链接","3.jpg");
        t1.start();
        t2.start();
        t3.start();
        }
    
    //下载器
    class WebDownloader{
        //下载方法
        public void downloader(String url,String name){
            try {
                FileUtils.copyURLToFile(new URL(url),new File(name));
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("IO异常,downloader方法出现问题");
            }
        }
    
    }
    }

实现Runnable接口(重点)

创建线程方式二 实现Runnable接口,重写run方法 执行线程需要丢入runnable接口实现类,调用start方法

package com.cjp;
    
    public class MyThread3 implements Runnable{
        @Override
        public void run() {
            //run方法线程体
            for (int i = 0; i < 20; i++) {
                System.out.println("子线程"+i);
            }
        }
    
        public static void main(String[] args) {
            //主线程
            //创建Runnable接口实现类的对象
            MyThread3 t = new MyThread3();
            //创建线程对象 通过线程对象来开启我们的线程,代理
            Thread thread = new Thread(t);
            thread.start();  //这两行代码等效于: new Thread(t).start();
    
            for (int i = 0; i < 20; i++) {
                System.out.println("主线程"+i);
            }
        }
    }
  • 多个线程操作同一个对象

抢票小游戏

package com.cjp;
    
    import javax.xml.namespace.QName;
    //多个线程操作同一个对象
    //模拟抢票
    //发现问题: 多个线程操作同一个资源的情况下,线程不安全,数据紊乱
    public class MyThread4 implements Runnable {
        //火车票的数目
        int ticketsnums = 10;
    
        @Override
        public void run() {
            while(true){
                if (ticketsnums<=0){
                    break;
                }
                //模拟延时
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"拿到了第"+ticketsnums--+"张票");
            }
        }
    
        public static void main(String[] args) {
            MyThread4 a = new MyThread4();
            new Thread(a,"小莫").start();
            new Thread(a,"小明").start();
            new Thread(a,"小红").start();
            new Thread(a,"小刚").start();
        }
    
    }

输出结果:

小莫拿到了第10张票

小刚拿到了第9张票

小明拿到了第8张票

小红拿到了第7张票

小红拿到了第5张票

小明拿到了第4张票

小莫拿到了第3张票

小刚拿到了第6张票

小红拿到了第2张票

小明拿到了第2张票

小刚拿到了第1张票

小莫拿到了第0张票

//输出结果不唯一

龟兔赛跑

 package com.cjp;
    //模拟龟兔赛跑
    public class MyThread 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(5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
    
                //判断比赛是否结束
                boolean flag = gameOver(i);
                if (flag){
                    break;
                }
                System.out.println(Thread.currentThread().getName()+"跑了"+i+"步");
            }
        }
    
        //判断是否完成比赛
        private boolean gameOver(int steps){
            //判断是否有胜利者
            if (winner!=null){ //已经存在胜利者了
                return true;
            }{
                if (steps>=100){
                    winner=Thread.currentThread().getName();
                    System.out.println("winner is"+winner);
                    return true;
                }
            }
            return false;
        }
    
        public static void main(String[] args) {
            MyThread s = new MyThread();
            new Thread(s,"乌龟").start();
            new Thread(s,"兔子").start();
        }
    }

输出结果:

乌龟跑了0步 兔子跑了0步 乌龟跑了1步 兔子跑了1步 乌龟跑了2步 兔子跑了2步 乌龟跑了3步 兔子跑了3步 乌龟跑了4步 兔子跑了4步 乌龟跑了5步 兔子跑了5步 乌龟跑了6步 兔子跑了6步 乌龟跑了7步 兔子跑了7步 乌龟跑了8步 兔子跑了8步 乌龟跑了9步 兔子跑了9步 乌龟跑了10步 乌龟跑了11步 乌龟跑了12步 乌龟跑了13步 乌龟跑了14步 乌龟跑了15步 乌龟跑了16步 乌龟跑了17步 乌龟跑了18步 乌龟跑了19步 乌龟跑了20步 乌龟跑了21步 乌龟跑了22步 乌龟跑了23步 乌龟跑了24步 乌龟跑了25步 乌龟跑了26步 乌龟跑了27步 乌龟跑了28步 乌龟跑了29步 乌龟跑了30步 乌龟跑了31步 乌龟跑了32步 乌龟跑了33步 乌龟跑了34步 乌龟跑了35步 乌龟跑了36步 乌龟跑了37步 乌龟跑了38步 乌龟跑了39步 乌龟跑了40步 乌龟跑了41步 乌龟跑了42步 乌龟跑了43步 乌龟跑了44步 乌龟跑了45步 乌龟跑了46步 乌龟跑了47步 乌龟跑了48步 乌龟跑了49步 乌龟跑了50步 乌龟跑了51步 乌龟跑了52步 乌龟跑了53步 乌龟跑了54步 乌龟跑了55步 乌龟跑了56步 乌龟跑了57步 乌龟跑了58步 乌龟跑了59步 乌龟跑了60步 乌龟跑了61步 乌龟跑了62步 乌龟跑了63步 乌龟跑了64步 乌龟跑了65步 乌龟跑了66步 乌龟跑了67步 乌龟跑了68步 乌龟跑了69步 乌龟跑了70步 乌龟跑了71步 乌龟跑了72步 乌龟跑了73步 乌龟跑了74步 乌龟跑了75步 乌龟跑了76步 乌龟跑了77步 乌龟跑了78步 乌龟跑了79步 乌龟跑了80步 乌龟跑了81步 乌龟跑了82步 乌龟跑了83步 乌龟跑了84步 乌龟跑了85步 乌龟跑了86步 乌龟跑了87步 乌龟跑了88步 乌龟跑了89步 乌龟跑了90步 乌龟跑了91步 乌龟跑了92步 乌龟跑了93步 乌龟跑了94步 乌龟跑了95步 乌龟跑了96步 乌龟跑了97步 乌龟跑了98步 乌龟跑了99步 winner is乌龟

实现Callable接口(了解)

1.实现Callable接口, 需要返回值类型

2.重写call方法,需要抛出异常

3.创建目标对象

4.创建执行服务: ExecutorService ser = Executors.newFixedThreadPool(1);

5.提交执行: Future result1 = ser.submit(t1);

6.获取结果: boolean r1 = result1.get() 7.关闭服务: ser.shutdownNow();

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值