多线程详解(狂神说)

多线程

## 学习自狂神##

概念

 

线程,进程,多线程

  • 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("天红要结婚了,开心😍");
    }
 }
 
 //代理角色,帮助你去结婚
 
 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 after() {
        System.out.println("结婚之后,收尾款");
    }
 
    private void before() {
        System.out.println("结婚之前,布置现场");
    }
 }

Lambda表达式

225QO0.md.png

22IpAU.md.png

22IYHf.md.png

 package TestLambda;
 
 /**
  * @Author 天红
  * @Date 2021/6/10 15:39
  * @Version 1.0
  */
 //推导Lambda表达式
 
 public class TestLambda01 {
 
        //   3.静态内部类
    static class Like2 implements ILike{
        @Override
        public void Lambda() {
            System.out.println("I like yan2");
        }
    }
 
 
    public static void main(String[] args) {
 
 
        ILike like=new Like();
        like.Lambda();
 
        like=new Like2();
        like.Lambda();
 
        //4.局部类部类
        class Like3 implements ILike{
            @Override
            public void Lambda() {
                System.out.println("I like yan3");
            }
        }
 
        like=new Like3();
        like.Lambda();
 
 
        //5.匿名内部类,没有类的名字,必须借助接口或者父类
        like=new ILike() {
            @Override
            public void Lambda() {
                System.out.println("I like yan4");
            }
        };
 
        like.Lambda();
 
        //用lambda简化
        like=() ->{
            System.out.println("I like yan5");
        };
        like.Lambda();
 
 
    }
 }
 
 //1.定义一个接口
 interface ILike{
    void Lambda();
 
 }
 
 
 //2.定义一个实现类
 class Like implements ILike{
 
    @Override
    public void Lambda() {
        System.out.println("I like yan");
    }
 }

线程状态

五大状态

 

22xpEd.md.png](https://i

22xyrD.md.png

22xvR0.md.png

线程停止举例

 package TestLambda;
 
 /**
  * @Author 天红
  * @Date 2021/6/10 17:27
  * @Version 1.0
  */
 public class TestStop implements Runnable{
    private boolean flag=true;
 
    @Override
    public void run() {
        int i=0;
        while (flag){
            System.out.println("run.....Thread"+i++);
      }
    }
 
    public void stop(){
        flag=false;
    }
 
    public static void main(String[] args) {
        TestStop t1=new TestStop();
        new Thread(t1).start();
 
 
        for (int i = 0; i < 100; i++) {
            System.out.println("mian"+i);
            if (i==99){
                t1.stop();
                System.out.println("线程该停止啦~");
            }
 
        }
 
    }
 }

线程休眠

2RPk2n.png

模拟网络延迟
package TestLambda;

/**
* @Author 天红
* @Date 2021/6/10 17:47
* @Version 1.0
*/


//多个线程操作同一个对象
// 买火车的例子

// 发现问题:多个线程操作一个资源的情况下,线程不安全,数据紊乱

// 模拟网络延迟,放大问题的的发生性
public class TestSleep implements Runnable {
private int ticketNums=10;

@Override
public void run() {
while (true){
if (ticketNums<=0){
break;
}

try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNums--+"票");
}

}


public static void main(String[] args) {
TestSleep ticket = new TestSleep();
new Thread(ticket,"天红").start();
new Thread(ticket,"老婆").start();
new Thread(ticket,"牛").start();
}
}
模拟倒计时
package TestLambda;

/**
* @Author 天红
* @Date 2021/6/10 17:57
* @Version 1.0
*/

//模拟倒计时
public class TestSleep2 {



public static void main(String[] args) {
try {
tenDown();
} catch (InterruptedException e) {
e.printStackTrace();
}

}

public static void tenDown() throws InterruptedException {
int num=10;
while (true){
Thread.sleep(1000);
System.out.println(num--);
if (num<0){
break;
}
}

}

}
打印倒计时
package TestLambda;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* @Author 天红
* @Date 2021/6/10 18:05
* @Version 1.0
*/
//打印倒计时
public class TestSleep3 {
public static void main(String[] args) {
// 打印当前系统时间
Date date = new Date(System.currentTimeMillis());
System.out.println(System.currentTimeMillis());
System.out.println(date);
while (true){
try {
Thread.sleep(1000);
System.out.println(new SimpleDateFormat("HH:mm:ss").format(date));
date = new Date(System.currentTimeMillis()); //更新当前时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

线程礼让(yield)

 

2RlRoj.md.png

2R3Qv6.md.png

join合并线程

2R32Ps.md.png

2R8neS.md.png

 

线程状态观测(五个)

2R8neS.md.png

线程状态举例
package TestLambda;

/**
* @Author 天红
* @Date 2021/6/10 19:55
* @Version 1.0
*/
public class TestState {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("=============");

});

//观察状态
Thread.State state = thread.getState();
System.out.println(state);
System.out.println("#########");

//观察启动后
thread.start(); //启动线程
state=thread.getState();
System.out.println(state); //运行

while (state!=Thread.State.TERMINATED){
Thread.sleep(1000);
state=thread.getState(); //更新线程状态
System.out.println(state); //输出状态
}


}
}

线程的优先级

2RBArd.png

2RBrL9.md.png

2RB5sH.md.png

守护线程(daemon)

概念

2RgG1P.png

守护线程测试
package TestLambda;

/**
* @Author 天红
* @Date 2021/6/10 21:38
* @Version 1.0
*/
public class TestDaemon {
public static void main(String[] args) {
You you = new You();
God god = new God();

Thread thread = new Thread(god);
thread.setDaemon(true); //默认flase表示守护线程
thread.start(); //上帝,守护线程启动

new Thread(you).start(); //你 用户线程启动

}
}


class You implements Runnable{

@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("你在开心的活着第"+i+"天");
}

System.out.println("===拜拜,我要去另外一个世界了===");

}
}


class God implements Runnable{
@Override

public void run() {
int i=0;

while (true){
System.out.println("神圣在保佑我"+i++);
}
}
}

线程同步

并发:

同一个对象被多个线程同时操作

线程同步概念2Rf2x1.md.png

synchronized2RhqkF.md.png

三大不安全的案例

不安全的买票

package TestLambda;

/**
* @Author 天红
* @Date 2021/6/12 19:14
* @Version 1.0
*/
//有负数
public class UnsafeBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket=new BuyTicket();
new Thread(buyTicket,"苦逼的我").start();
new Thread(buyTicket,"牛逼的你们").start();
new Thread(buyTicket,"荒天帝").start();

}
}

class BuyTicket implements Runnable{
private int ticketNum=10;
boolean flag=true;
@Override
public void run() {
while (flag) {
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void buy() throws InterruptedException {
if (ticketNum<=0){
flag=false;
return;
}
Thread.sleep(100);
System.out.println(Thread.currentThread().getName()+"买了第"+ticketNum--+"张票");
}
}

不安全的银行

 package TestLambda;
 
 /**
  * @Author 天红
  * @Date 2021/6/12 20:29
  * @Version 1.0
  */
 public class UnsafeBank {
    public static void main(String[] args) {
        Account account = new Account(100,"结婚钱");
        new Drawing(account,50,"你").start();
        new Drawing(account,100,"你老婆").start();
 
 
 
    }
 }
 
 //账户
 class Account{
    int money; //余额
    String name;   //卡名
 
    public Account(int money, String name) {
        this.money = money;
        this.name = name;
    }
 }
 
 //银行:模拟取款
 class Drawing extends Thread{
    Account account;       //账户
 
    //取了多少钱
    int drawingMoney;
 
    //现在手里有多少钱
    int nowMoney;
 
    public Drawing(Account account, int drawingMoney,String name) {
        super(name);
        this.account = account;
        this.drawingMoney = drawingMoney;
 
    }
 
    @Override
    public void run() {
        //判断有没有钱
        if (account.money-drawingMoney<0){
            System.out.println(Thread.currentThread().getName()+"钱不够,取不了");
            return;
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        account.money=account.money-drawingMoney;   //卡内余额=余额-取的钱
        nowMoney=drawingMoney+nowMoney;     //手里的钱=取的钱+原来手里的钱
 
        System.out.println(account.name+"当前的余额为:"+account.money);
 //       System.out.println(Thread.currentThread().getName()+"手里的钱:"+nowMoney);
        System.out.println(this.getName()+"手里的钱:"+nowMoney);
    }
 }

不安全的集合

package TestLambda;

import java.util.ArrayList;
import java.util.List;

/**
* @Author 天红
* @Date 2021/6/12 21:05
* @Version 1.0
*/
public class UnsafeList {
public static void main(String[] args) throws InterruptedException {
List<String> list=new ArrayList<String>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
Thread.sleep(10);
System.out.println(list.size());
}
}

同步方法及同步块

2I0RaQ.md.png

2I0HqU.md.png

安全的买票

一个对象直接在需要执行的方法上加上synchronized

package TestLambda;

/**
* @Author 天红
* @Date 2021/6/12 19:14
* @Version 1.0
*/
public class SafeBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket=new BuyTicket();
new Thread(buyTicket,"苦逼的我").start();
new Thread(buyTicket,"牛逼的你们").start();
new Thread(buyTicket,"荒天帝").start();

}
}

class BuyTicket implements Runnable{
private int ticketNum=10;
boolean flag=true;
@Override
public void run() {
while (flag) {
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

//synchronized锁的是this
public synchronized void buy() throws InterruptedException {
if (ticketNum<=0){
flag=false;
return;
}
Thread.sleep(100);
System.out.println(Thread.currentThread().getName()+"买了第"+ticketNum--+"张票");
}
}

安全的银行

package TestLambda;

/**
* @Author 天红
* @Date 2021/6/12 20:29
* @Version 1.0
*/
public class SafeBank {
public static void main(String[] args) {
Account account = new Account(1000,"结婚钱");
new Drawing(account,50,"你").start();
new Drawing(account,100,"你老婆").start();
}
}
//账户
class Account{
int money; //余额
String name; //卡名
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}

//银行:模拟取款
class Drawing extends Thread{
Account account; //账户
int drawingMoney; //取了多少钱
int nowMoney; //现在手里有多少钱
public Drawing(Account account, int drawingMoney,String name) {
super(name);
this.account = account;
this.drawingMoney = drawingMoney;
}
@Override
public void run() {

//锁的对象就是变化的量,需要增删改的对象,锁共享的对象,唯一的对象
synchronized (account){
//判断有没有钱
if (account.money-drawingMoney<0){
System.out.println(Thread.currentThread().getName()+"钱不够,取不了");
return;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.money=account.money-drawingMoney; //卡内余额=余额-取的钱
nowMoney=drawingMoney+nowMoney; //手里的钱=取的钱+原来手里的钱

System.out.println(account.name+"当前的余额为:"+account.money);
// System.out.println(Thread.currentThread().getName()+"手里的钱:"+nowMoney);
System.out.println(this.getName()+"手里的钱:"+nowMoney);

}
}
}

安全的集合

package TestLambda;

import java.util.ArrayList;
import java.util.List;

/**
* @Author 天红
* @Date 2021/6/12 21:05
* @Version 1.0
*/
public class SafeList {
public static void main(String[] args) throws InterruptedException {
List<String> list=new ArrayList<String>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
synchronized (list){
list.add(Thread.currentThread().getName());
}
}).start();
}
Thread.sleep(2000);
System.out.println(list.size());
}
}

JUC(CopyOnWriteArrayList)

package TestLambda;

import java.util.concurrent.CopyOnWriteArrayList;

/**
* @Author 天红
* @Date 2021/6/13 11:29
* @Version 1.0
*/

//测试JUC(就是并发包)安全类型的集合,安全的
public class TestJUC {
public static void main(String[] args) throws InterruptedException {
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}

Thread.sleep(2000); //为什么要睡眠,不睡还没add完,mian主线程一下就跑完了

System.out.println(list.size());
}
}

死锁

2ILOGd.md.png

死锁的例子

package TestLambda;

/**
* @Author 天红
* @Date 2021/6/13 14:46
* @Version 1.0
*/
public class DeadLock {
public static void main(String[] args) {
Makeup m1=new Makeup(0,"苏苏");
Makeup m2=new Makeup(1,"老婆");
m1.start();
m2.start();


}
}
//口红
class Lipstick{

}

//镜子
class Mirror{

}

class Makeup extends Thread{
// 需要的资源只有一份,用static来保证只有一份
static Lipstick lipstick=new Lipstick();
static Mirror mirror=new Mirror();

int choice; //选择
String girlName; //使用化妆品的人

public Makeup(int choice, String girlName) {
this.choice = choice;
this.girlName = girlName;
}

@Override
public void run() {
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

private void makeup() throws InterruptedException {
if (choice==0){
synchronized (lipstick){
System.out.println(this.girlName+"获得了口红的锁");
Thread.sleep(1000);
synchronized (mirror){ //一秒钟后想获得镜子的锁
System.out.println(this.girlName+"获得镜子的锁");
}
}
}else{
synchronized (mirror){
System.out.println(this.girlName+"获得了镜子的锁");
Thread.sleep(2000);
synchronized (lipstick){ // 2秒钟后想获得口红的锁
System.out.println(this.girlName+"获得口红的锁");
}
}

}

}


}

死锁的解决

package TestLambda;

/**
* @Author 天红
* @Date 2021/6/13 14:46
* @Version 1.0
*/
public class DeadLock {
public static void main(String[] args) {
Makeup m1=new Makeup(0,"苏苏");
Makeup m2=new Makeup(1,"老婆");
m1.start();
m2.start();


}
}
//口红
class Lipstick{

}

//镜子
class Mirror{

}

class Makeup extends Thread{
// 需要的资源只有一份,用static来保证只有一份
static Lipstick lipstick=new Lipstick();
static Mirror mirror=new Mirror();

int choice; //选择
String girlName; //使用化妆品的人

public Makeup(int choice, String girlName) {
this.choice = choice;
this.girlName = girlName;
}

@Override
public void run() {
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

private void makeup() throws InterruptedException {
if (choice==0){
synchronized (lipstick){
System.out.println(this.girlName+"获得了口红的锁");
Thread.sleep(1000);
}
synchronized (mirror){ //一秒钟后想获得镜子的锁
System.out.println(this.girlName+"获得镜子的锁");
}
}else{
synchronized (mirror){
System.out.println(this.girlName+"获得了镜子的锁");
Thread.sleep(2000);
}
synchronized (lipstick){ // 2秒钟后想获得口红的锁
System.out.println(this.girlName+"获得口红的锁");
}

}

}


}

2oSdTP.md.png

Lock锁

2olKvd.md.png

可重入锁 ReentrantLock()

 package TestLambda;
 
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
 /**
  * @Author 天红
  * @Date 2021/6/13 17:13
  * @Version 1.0
  */
 public class TestLock {
    public static void main(String[] args) {
        TestLock02 testLock02 = new TestLock02();
 
        new Thread(testLock02).start();
        new Thread(testLock02).start();
        new Thread(testLock02).start();
 
    }
 }
 
 class TestLock02 implements Runnable{
    int ticketNums=1000;
    //定义lock锁i
    private final ReentrantLock lock=new ReentrantLock();
 
 
    @Override
    public void run() {
 
        while (true){
            try{
                lock.lock();   //加锁
                if (ticketNums>0){
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"-->"+ticketNums--);
                }
                else {
                    break;
                }
 
 
            }finally {
                lock.unlock(); //解锁
            }
        }
    }
 }

2oGz6g.md.png

对比

2oJP7n.md.png

线程协作(生产者消费者模式)

线程通信

2o0t0S.md.png

2o0QfA.md.png

2o0sXV.md.png

解决方式

管程法
package TestLambda;

/**
* @Author 天红
* @Date 2021/6/13 19:54
* @Version 1.0
*/
//测试:生产者消费者模型 ,利用缓冲区解决:管程法
//生产者,消费者,长跑,缓冲区
public class TestPC {

public static void main(String[] args) {
SynContainer c = new SynContainer();
new Producer(c).start();
new Consumer(c).start();

}

}
//生产者
class Producer extends Thread{
SynContainer container;
public Producer(SynContainer container) {
this.container = container;
}

//生产
@Override
public void run() {
for(int i=1;i<=100;i++)
{
container.push(new Chicken(i));
System.out.println("生产了第"+i+"只鸡");
}
}
}
//消费者
class Consumer extends Thread{
SynContainer container;
public Consumer(SynContainer container) {
this.container = container;
}

//消费
@Override
public void run() {
for(int i=1;i<=100;i++)
{
System.out.println("消费了第"+container.pop().id+"只鸡");
}
}
}
//产品
class Chicken{
int id;//编号
public Chicken(int id)
{
this.id = id;
}
}
//缓冲区
class SynContainer{
//容器大小
Chicken[] chickens = new Chicken[10];
//容器计数器
int count = 0;

//生产者放入产品
public synchronized void push(Chicken chicken)
{
//如果容器满了,就需要等待消费者消费
if(count == chickens.length)
{
//通知消费者消费,生产等待
try {
this.wait();
}catch(Exception e) {
e.printStackTrace();
}
}
//如果没有满,我们就需要丢入产品
chickens[count] = chicken;
count++;
//可以通知消费者了
this.notifyAll();
}

//消费者消费产品
public synchronized Chicken pop() {
//判断能否消费
if(count==0)
{
//等待生产者生产,消费者等待
try {
this.wait();
}catch(Exception e)
{
e.printStackTrace();
}
}

//如果可以消费
count--;
Chicken chicken = chickens[count];
//吃完了,通知生产者生产
this.notifyAll();
return chicken;
}
}

#####

2o04pR.md.png

信号灯法
 package TestLambda;
 
 /**
  * @Author 天红
  * @Date 2021/6/13 20:33
  * @Version 1.0
  */
 //测试生产消费者问题2,信号灯法,标志位解决
 public class TestPC2 {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        TV tv = new TV();
        new player(tv).start();
        new Watcher(tv).start();
    }
 }
 //生产者-》演员
 class player extends Thread{
    TV tv;
    public player(TV tv)
    {
        this.tv = tv;
    }
 
    @Override
    public void run() {
        for(int i=0;i<20;i++)
        {
            if(i%2==0)
            {
                this.tv.play("完美世界");
            }
            else
            {
                this.tv.play("快来bibi看狂神");
            }
        }
    }
 }
 //消费者-》观众
 class Watcher extends Thread{
    TV tv;
    public Watcher(TV tv)
    {
        this.tv = tv;
    }
    @Override
    public void run() {
        for(int i=0;i<20;i++)
        {
            tv.watch();
        }
    }
 }
 //产品-》节目
 class TV {
    //演员录制,观众等待
    //观众观看,演员等待
    String voice;//表演的节目
    boolean flag = true;
 
    //录制
    public synchronized void play(String voice) {
        if(!flag)
        {
            try {
                this.wait();
            }catch(Exception e)
            {
                e.printStackTrace();
            }
        }
        System.out.println("演员录制了"+voice);
        //通知观众观看
        this.notifyAll();
        this.voice = voice;
        this.flag = !this.flag;
    }
 
    //观众看
    public synchronized void watch() {
        if(flag)
        {
            try {
                this.wait();
            }catch(Exception e)
            {
                e.printStackTrace();
            }
        }
 
        System.out.println("观看了"+voice);
        //通知演员录制
        this.notifyAll();
        this.flag = !this.flag;
    }
 }

2o0Xhd.md.png

线程池

2oTEcV.md.png

2oTYnO.md.png

ExecutorService和Executors

 package TestLambda;
 
 /**
  * @Author 天红
  * @Date 2021/6/13 20:48
  * @Version 1.0
  */
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
 //测试线程池
 public class TestPool {
 
    public static void main(String[] args) {
 
        //1.创建线程池
        ExecutorService service = Executors.newFixedThreadPool(10);
 
        //执行
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());
        //关闭连接
        service.shutdown();
    }
 
 }
 class MyThread implements Runnable{
    @Override
    public void run() {
 
            System.out.println(Thread.currentThread().getName());
         
    }
 }

总结

 package TestLambda;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.FutureTask;
 
 /**
  * @Author 天红
  * @Date 2021/6/13 20:59
  * @Version 1.0
  */
 
 //回顾总结线程的创建
 public class ThreadNew {
    public static void main(String[] args) {
        new MyThread1().start();
        new Thread(new MyThread2()).start();
 
        FutureTask<Integer> f = new FutureTask<Integer>(new MyThread3());
        new Thread(f).start();
        try {
            Integer i = f.get();
            System.out.println(i);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 }
 
 //1.继承Thread类
 class MyThread1 extends Thread {
    @Override
    public void run() {
        System.out.println("MyThread1");
    }
 }
 
 //2.实现Runnable接口
 class MyThread2 implements Runnable {
    @Override
    public void run() {
        System.out.println("MyThread2");
    }
 }
 
 //3.实现Callable接口
 class MyThread3 implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        System.out.println("MyThread3");
        return 100;
    }
 }
posted @ 2021-06-14 19:10  你我不在年少  阅读(493)  评论(0编辑  收藏  举报