JAVA 多线程一 JAVA从基础开始 -- 3

JAVA 多线程一 JAVA从基础开始 -- 3,第1张

JAVA 多线程一 JAVA从基础开始 -- 3

JAVA 多线程一 JAVA从基础开始 -- 3
  • 线程简介
  • 线程创建
    • 继承Thread类
      • 网图下载 (案例)
    • 实现Runnable接口
    • 下载图片案例
      • 并发线程
    • 实现Callable接口
    • 静态代理

线程简介

任务,进程,线程,多线程

一个个体一起做多个事情叫多任务,

Process 进程 (执行程序的一次执行过程,是动态,系统分配的单位)
Thread 线程 (一个进程包含若干线程,一个进程至少有一个线程,否则没存在意义,线程是CPU调度的执行的单位)

注意:很多多线程是模拟出来的,真正的多线程是指有多个cpu,即多核,如服务器。如果是模拟出来的多线程,即在一个cpu的情况下,在同一个时间点,cpu只能执行一个代码,因为切换的很快,所以就有同时执行的错局。

–线程是独立的执行路径

◆线程就是独立的执行路径;
◆在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,g线程
◆main()称之为主线程,为系统的入口,用于执行整个程序
◆在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与 *** 作系统紧密相关的,先后顺序是不能认为的干预的
◆对同一份资源 *** 作时,会存在资源抢夺的问题,需要加入并发控制
;◆线程会带来额外的开销,如cpu调度时间,并发控制开销
◆每个线程在自己的工作内存交互,内存控制不当会造成数据不一致

线程创建 继承Thread类

继承Thread类,重写run方法

//jdk文档
class PrimeThread extends Thread {
         long minPrime;
         PrimeThread(long minPrime) {
             this.minPrime = minPrime;
         }
 
         public void run() {//重写run方法
             // compute primes larger than minPrime
              . . .
         }
     }

重写run方法,执行该父类(Thread)的start()方法,开启新线程,与主线程异步工作!

package aaa;
//创建线程方式:继承THread类,重写run()方法,调用start开启线程
public class MyThread extends Thread{
    @Override
    public void run() {
//       run方法线程
        for (int i = 0; i < 5; i++) {
            System.out.println("run:"+i);
        }
    }

    public static void main(String[] args) {
        //创建线程对象
        MyThread myThread = new MyThread();
        //调用start()开启线程
        myThread.start();

        //main线程
        for (int i = 0; i < 1100; i++) {
            System.out.println("main:"+i);
        }
    }
}

可以看到,在main方法遍历1100过程中,可看到另一条新线程正在遍历5

网图下载 (案例)

需要下载commons-io-2.6.jar.
实现代码:

package aaa;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;

//联系Thread 实现多线程下载图片
public class MyThread1 extends Thread {
   private String url;//网络地址
   private String name;//文件名

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

   @Override
   public void run() {
       WebDownLoader webDownLoader = new WebDownLoader();
       webDownLoader.downLoader(url, name);
       System.out.println("下载了:" + url + name);
   }

   public static void main(String[] args) {
       MyThread1 t1 = new MyThread1("https://img-home.csdnimg.cn/images/20201124032511.png", "1.png");
       MyThread1 t2 = new MyThread1("https://csdnimg.cn/release/blogv2/dist/pc/img/original.png", "2.png");
       MyThread1 t3 = new MyThread1("https://csdnimg.cn/release/blogv2/dist/pc/img/articleReadEyes.png", "3.png");
       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");
       }
   }
}

运行打印

由后台打印可以看出,进行下载的图片并不是按1,2,3的顺序下载的,说明这3张图片是3个不同的线程进行了下载。

不建议使用:避免OOP单继承局限性(在Java中一个类只能使用extends继承一个父类.)

实现Runnable接口

创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。采用这种风格的同一个例子如下所示:

//jdk文档
 class PrimeRun implements Runnable {
         long minPrime;
         PrimeRun(long minPrime) {
             this.minPrime = minPrime;
         }
 
         public void run() {
             // compute primes larger than minPrime
              . . .
         }
     }
     //然后,下列代码会创建并启动一个线程:

     PrimeRun p = new PrimeRun(143);
     new Thread(p).start();

实现

package aaa;

//创建线程方式2 实现Runnable接口 ,重写run方法,执行线程需要丢入runnable的实现类,调用start
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        //run方法线程
        for (int i = 0; i < 5; i++) {
            System.out.println("run:" + i);
        }
    }

    public static void main(String[] args) {
        //创建线程对象
        MyRunnable myRunnable = new MyRunnable();
        //创建线程对象,通过线程对象开启我们 的线程,,代理方式
//        Thread thread = new Thread(myRunnable);
//        thread.start();

        new Thread(myRunnable).start();
        //main线程
        for (int i = 0; i < 1100; i++) {
            if(i / 9 == 0){
                System.out.println("main:" + i);
            }else{
                System.out.println("main:");
            }
        }
    }
}

打印:

已经实现了创建新线程运行

下载图片案例

稍改动实现

package aaa;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;

//联系Thread 实现多线程下载图片
public class MyRunnable1 implements Runnable {
    private String url;//网络地址
    private String name;//文件名

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

    @Override
    public void run() {
        WebDownLoaders webDownLoader = new WebDownLoaders();
        webDownLoader.downLoader(url, name);
        System.out.println("下载了:" + url + name);
    }

    public static void main(String[] args) {
        MyRunnable1 t1 = new MyRunnable1("https://img-home.csdnimg.cn/images/20201124032511.png", "4.png");
        MyRunnable1 t2 = new MyRunnable1("https://csdnimg.cn/release/blogv2/dist/pc/img/original.png", "5.png");
        MyRunnable1 t3 = new MyRunnable1("https://csdnimg.cn/release/blogv2/dist/pc/img/articleReadEyes.png", "6.png");

        new Thread(t1).start();
        new Thread(t2).start();
        new Thread(t3).start();

        //        t1.start();
//        t2.start();
//        t3.start();
    }
}

//下载器
class WebDownLoaders {
    //下载方法
    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");
        }
    }
}


实现了多线程运行

推荐使用:避免单继承局限性,灵活方便,方便同一对象被多个线程使用

并发线程

在多线程 *** 作同一对象,出现数据混乱的问题

实现Callable接口

了解为主
改变下载图片案例

package domo02;

import org.apache.commons.io.FileUtils;

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

//线程创建方式:实现callable
//可以有返回值
//可以抛出异常
public class TestCallable implements Callable {
        private String url;//网络地址
        private String name;//文件名

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

        @Override
        public Boolean call() {
            WebDownLoaders webDownLoader = new WebDownLoaders();
            webDownLoader.downLoader(url, name);
            System.out.println("下载了:" + url + name);
            return true;
        }

        public static void main(String[] args) throws ExecutionException, InterruptedException {
            TestCallable t1 = new TestCallable("https://img-home.csdnimg.cn/images/20201124032511.png", "c4.png");
            TestCallable t2 = new TestCallable("https://csdnimg.cn/release/blogv2/dist/pc/img/original.png", "5.png");
            TestCallable t3 = new TestCallable("https://csdnimg.cn/release/blogv2/dist/pc/img/articleReadEyes.png", "c6.png");

            //创建执行服务
            ExecutorService ser = Executors.newFixedThreadPool(3);
            //提交执行
            Future r1 = ser.submit(t1);
            Future r2 = ser.submit(t2);
            Future r3 = ser.submit(t3);
            //获取结果
            boolean rs1 = r1.get();
            boolean rs2 = r2.get();
            boolean rs3 = r3.get();
            //关闭服务
            ser.shutdownNow();
        }
    }

    //下载器
    class WebDownLoaders {
        //下载方法
        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");
            }
        }
    }
静态代理

你:真实角色
婚庆公司:代理你,帮你处理结婚的事情
结婚:你实现结婚接口即可

演示:实现静态代理对比Thread

package proxy;
//静态代理模式
//真实对象和代理对象都要实现同一个接口
//代理对象要代理真实角色  You
//好处
//  代理对象可以做很多真实对象做不了的事情
//    真实对象专注做自己的事情
public class StacticProxy {
    public static void main(String[] args) {

        //Thread对象代理了()-> System.out.println("123456")来执行
        new Thread(()-> System.out.println("123456")).start();


        You you = new You("me");//结婚对象
        WeddingCompany weddingCompany= new WeddingCompany(you);//把对象给到代理对象
        weddingCompany.HappyMarry();
    }

}

interface Marry {
    void HappyMarry();
}

//你自己
class You implements Marry {
    private String name;

    public You(String name) {
        this.name = name;
    }

    @Override
    public void HappyMarry() {
        System.out.println(name + "要结婚了");
    }
}

//代理角色
class WeddingCompany implements Marry {
//    真实目标角色
    private Marry target;

    public WeddingCompany(Marry target) {
        this.target = target;
    }

    @Override
    public void HappyMarry() {
        //结婚之前
        before();
        this.target.HappyMarry();
        after();
    }

    private void before() {
        System.out.println("结婚之前布置现场");
    }

    private void after() {
        System.out.println("结婚之后收尾款");
    }
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5693189.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存