首页 > 技术文章 > 多线程详解(狂神说)

th11 2021-06-14 19:10 原文

多线程

## 学习自狂神##

概念

 

线程,进程,多线程

  • 20Pm4S.md.png

  • 20ieq1.md.png

  • 20ivWD.md.png

线程创建

 [![20km4K.md.png](https://z3.ax1x.com/2021/06/07/20km4K.md.png)](https://imgtu.com/i/20km4K)

 

20V3DJ.md.png

继承Thread类

  • 20eAkn.md.png

网图下载

 package th.demo01;
 
 import org.apache.commons.io.FileUtils;
 
 import java.io.File;
 import java.io.IOException;
 import java.net.URL;
 
 /**
  * @Author 天红
  * @Date 2021/6/7 20:04
  * @Version 1.0
  */
 //练习Thread,实现多线程同步下载图片
 
 public class TestThread1 extends Thread{
    private String url;
    private String name;
 
    public TestThread1(String url, String name) {
        this.url = url;
        this.name = name;
    }
 
 //   下载图片线程的执行体
    @Override
    public void run() {
        WebDownLLoader webDownLLoader = new WebDownLLoader();
        webDownLLoader.downLoad(url,name);
        System.out.println("下载了文件名为:"+name);
    }
 
    public static void main(String[] args) {
        TestThread1 t1 = new TestThread1("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.jj20.com%2Fup%2Fallimg%2F1114%2F0G520141919%2F200G5141919-2-1200.jpg&refer=http%3A%2F%2Fpic.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660613&t=47d43ca821a757183016d42c33ec8b41","1.jpg");
        TestThread1 t2 = new TestThread1("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fclubimg.club.vmall.com%2Fdata%2Fattachment%2Fforum%2F202004%2F28%2F232538icfogvlsgjywjw36.jpg&refer=http%3A%2F%2Fclubimg.club.vmall.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660613&t=0b38b8beab9576e4a06f51f6c81c70a5","2.jpg");
        TestThread1 t3 = new TestThread1("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201603%2F04%2F20160304192803_HRdrS.thumb.700_0.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660908&t=1a2a2fb9358036ee12f43e25b1e3564f","3.jpg");
        t1.start();
        t2.start();
        t3.start();
    }
 
 }
 
 //下载器
 class WebDownLLoader{
 //   下载方法
    public void downLoad(String url,String name){
        try {
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO异常");
        }
 
    }
 }

实现Runnable接口

 package th.demo01;
 
 import org.apache.commons.io.FileUtils;
 
 import java.io.File;
 import java.io.IOException;
 import java.net.URL;
 
 /**
  * @Author 天红
  * @Date 2021/6/7 20:04
  * @Version 1.0
  */
 //练习Thread,实现多线程同步下载图片
 
 public class TestThread1 implements Runnable{
    private String url;
    private String name;
 
    public TestThread1(String url, String name) {
        this.url = url;
        this.name = name;
    }
 
 //   下载图片线程的执行体
    @Override
    public void run() {
        WebDownLLoader webDownLLoader = new WebDownLLoader();
        webDownLLoader.downLoad(url,name);
        System.out.println("下载了文件名为:"+name);
    }
 
    public static void main(String[] args) {
        TestThread1 t1 = new TestThread1("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.jj20.com%2Fup%2Fallimg%2F1114%2F0G520141919%2F200G5141919-2-1200.jpg&refer=http%3A%2F%2Fpic.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660613&t=47d43ca821a757183016d42c33ec8b41","1.jpg");
        TestThread1 t2 = new TestThread1("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fclubimg.club.vmall.com%2Fdata%2Fattachment%2Fforum%2F202004%2F28%2F232538icfogvlsgjywjw36.jpg&refer=http%3A%2F%2Fclubimg.club.vmall.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660613&t=0b38b8beab9576e4a06f51f6c81c70a5","2.jpg");
        TestThread1 t3 = new TestThread1("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201603%2F04%2F20160304192803_HRdrS.thumb.700_0.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660908&t=1a2a2fb9358036ee12f43e25b1e3564f","3.jpg");
        new Thread(t1).start();
        new Thread(t2).start();
        new Thread(t3).start();
    }
 
 }
 
 //下载器
 class WebDownLLoader{
 //   下载方法
    public void downLoad(String url,String name){
        try {
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO异常");
        }
 
    }
 }

20HYwj.md.png

小节

2rjgiD.md.png

####

初始并发问题

买火车票例子
 package th.demo01;
 
 /**
  * @Author 天红
  * @Date 2021/6/7 21:01
  * @Version 1.0
  */
 
 //多个线程操作同一个对象
 //   买火车的例子
 
 //   发现问题:多个线程操作同一个资源的情况下,线程不安全,数据紊乱
 public class TestThread2 implements Runnable {
    private int ticketNums=10;
 
    @Override
    public void run() {
        while (true){
            if (ticketNums<=0){
                break;
            }
 
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
 
            System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNums--+"票");
        }
 
    }
 
 
    public static void main(String[] args) {
        TestThread2 ticket = new TestThread2();
        new Thread(ticket,"天红").start();
        new Thread(ticket,"老婆").start();
        new Thread(ticket,"牛").start();
    }
 }
龟兔赛跑

20xQs0.md.png

 

 package th.demo01;
 
 /**
  * @Author 天红
  * @Date 2021/6/7 21:29
  * @Version 1.0
  */
 public class Race implements Runnable{
 //   胜利者
    private static String winner;
 
 
    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {
 
 //           模拟兔子休息
                if (Thread.currentThread().getName().equals("兔子")&&i%10==0){
                    try {
                        Thread.sleep(1);
                    } 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) {
        Race race = new Race();
        new Thread(race,"兔子").start();
        new Thread(race,"乌龟").start();
 
    }
 }

实现Callable接口(了解即可)

2rxkAf.md.png

 package th.demo01;
 
 import org.apache.commons.io.FileUtils;
 
 import java.io.File;
 import java.io.IOException;
 import java.net.URL;
 import java.util.concurrent.*;
 
 /**
  * @Author 天红
  * @Date 2021/6/8 19:40
  * @Version 1.0
  */
 
 
  //callable的好处
  //1,可以定义返回值
  //2,可以抛出异常
 
 public class TestCallable implements Callable<Boolean> {
    private String url;
    private String name;
 
    public TestCallable(String url, String name) {
        this.url = url;
        this.name = name;
    }
 
    //   下载图片线程的执行体
    @Override
    public Boolean call() {
        WebDownLLoader webDownLLoader = new WebDownLLoader();
        webDownLLoader.downLoad(url, name);
        System.out.println("下载了文件名为:" + name);
        return true;
    }
 
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestCallable t1 = new TestCallable("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.jj20.com%2Fup%2Fallimg%2F1114%2F0G520141919%2F200G5141919-2-1200.jpg&refer=http%3A%2F%2Fpic.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660613&t=47d43ca821a757183016d42c33ec8b41", "1.jpg");
        TestCallable t2 = new TestCallable("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fclubimg.club.vmall.com%2Fdata%2Fattachment%2Fforum%2F202004%2F28%2F232538icfogvlsgjywjw36.jpg&refer=http%3A%2F%2Fclubimg.club.vmall.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660613&t=0b38b8beab9576e4a06f51f6c81c70a5", "2.jpg");
        TestCallable t3 = new TestCallable("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201603%2F04%2F20160304192803_HRdrS.thumb.700_0.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660908&t=1a2a2fb9358036ee12f43e25b1e3564f", "3.jpg");
 
 
 
 //       创建执行服务
        ExecutorService service = Executors.newFixedThreadPool(3);
 
 //       提交执行
        Future<Boolean> r1 = service.submit(t1);
        Future<Boolean> r2 = service.submit(t2);
        Future<Boolean> r3 = service.submit(t3);
 
        boolean res1 = r1.get();
        boolean res2 = r1.get();
        boolean res3 = r1.get();
         
         
        System.out.println(res1);
        System.out.println(res2);
        System.out.println(res3);
 
 
 //       关闭服务
        service.shutdown();
 
    }
 
 
    //下载器
    class WebDownLLoader {
        //   下载方法
        public void downLoad(String url, String name) {
            try {
                FileUtils.copyURLToFile(new URL(url), new File(name));
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("IO异常");
            }
 
        }
    }
 }

静态代理模式

 package th.demo01;
 
 /**
  * @Author 白天红
  * @Date 2021/6/8 20:13
  * @Version 1.0
  */
 
 
 //静态代理模式总结:
 //   真实对象和代理对象都要实现同一个接口
 //   代理角色要代理真实角色
 
 //   好处
    //代理对象可以做真实对象做不了的事情
    //真实对象专注做自己的事情
 public class StaticProxy {
    public static void main(String[] args) {
 
        new Thread(()-> System.out.println("我爱你")).start();
 // 是不是一样,线程底部就用了静态代理模式
 
        new WeddingCompany(new You()).happyMarry();
 
    }
 }
 
 interface Marry{
    void happyMarry();
 
 }
 
 //真实角色,你去结婚
 class You implements Marry{
 
    @Override
    public void happyMarry() {
        System.out.println("天红要结婚了,开心

推荐阅读