多线程基础 [线程五大状态、死锁、线程同步、线程协作]

多线程

线程,进程,任务,多线程 ,程序??
程序:是指指令和数据的有序集合,其本身没有运行的含义,是一个静态的概念
进程:是指执行程序的一次执行过程,是一个动态的概念,是电脑分配资源的一个单位
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1.线程

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

2.线程的创建

Thread , Runnable ,Callable
在这里插入图片描述

2.1 Thread类

在这里插入图片描述在这里插入图片描述

自定义线程类继承Thread

//多线程的创建方式一 ,继承thread类并且重写run()方法
//注意线程开启,不一定先执行,只要看cpu调度谁先开始
public class ThreadTest extends Thread {
    @Override
    public void run() {
        //run方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("我在看代码"+i);
        }
    }
    public static void main(String[] args) {
        //创建一个线程对象
        ThreadTest test = new ThreadTest();
        //执行start()方法,开启线程
        test.start();
        //主方法线程体
        for (int i = 0; i < 200; i++) {
            System.out.println("我在学习多线程"+i);
        }
    }
}

在这里插入图片描述使用多线程下载图片

import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
 * Created by MR.ZHANG on 2020/7/31 15:32
 */
//使用多线程下载图片
public class ThreadTest2 extends Thread{
    private String url;//网络图片的url
    private String name;//文件名字

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

    @Override
    //下载图片线程体
    public void run() {
        webDownLoad downLoad = new webDownLoad();
        downLoad.download(url,name);
        System.out.println("下载了图片");
    }
    public static void main(String[] args) {
        ThreadTest2 threadTest2 = new ThreadTest2("https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1596178880&di=bdd01c5e3da4d69f38286754154454cc&src=http://img.yzt-tools.com/20190708/7bbf9da8ff29079c6f3f8e9e47d17b0b.jpg?x-oss-process=image/resize,w_600/auto-orient,1/quality,q_90/format,jpg","1.jpg");
        ThreadTest2 threadTest1 = new ThreadTest2("https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1596178880&di=bdd01c5e3da4d69f38286754154454cc&src=http://img.yzt-tools.com/20190708/7bbf9da8ff29079c6f3f8e9e47d17b0b.jpg?x-oss-process=image/resize,w_600/auto-orient,1/quality,q_90/format,jpg","1.jpg");
        ThreadTest2 threadTest3 = new ThreadTest2("https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1596178880&di=bdd01c5e3da4d69f38286754154454cc&src=http://img.yzt-tools.com/20190708/7bbf9da8ff29079c6f3f8e9e47d17b0b.jpg?x-oss-process=image/resize,w_600/auto-orient,1/quality,q_90/format,jpg","1.jpg");

        threadTest1.start();
        threadTest2.start();
        threadTest3.start();
    }

}
//下载器类
class  webDownLoad {
    //下载方法
    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异常,download方法出现问题");
        }
    }
}

在这里插入图片描述

2.2 实现Runnable接口

在这里插入图片描述

package Test;

/**
 * Created by MR.ZHANG on 2020/7/31 16:16
 */

//创建线程方式2,实现runnable接口 ,重写run方法 ,执行线程需要丢入runnable接口实现类,调用start方法
public class TestThread3  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实例对象
//        TestThread3 testThread3 = new TestThread3();
//        //创建线程对象,并将runnable实例对象丢进去
//        Thread thread = new Thread(testThread3);
        new Thread(new TestThread3()).start();

        for (int i = 0; i < 200; i++) {
            System.out.println("我在学习多线程"+i);
        }
    }
}

在这里插入图片描述

多个线程操作一个对象

package Test;
/**
 * Created by MR.ZHANG on 2020/7/31 16:27
 */
//多个线程操作一个对象  模拟买票服务
//多个线程操作同一个资源,线程不安全会造成线程紊乱
public class ThreadTest4 implements Runnable{
    private int ticketNums =50;//票数
    @Override
    public void run() {
        while(true){
            if (ticketNums<=0){
                break;
            }
            System.out.println(Thread.currentThread().getName()+"拿到了第"+ticketNums-- +"票" );
        }
    }
    public static void main(String[] args) {
        ThreadTest4 threadTest4 = new ThreadTest4();
        new Thread(threadTest4,"黄牛").start();
        new Thread(threadTest4,"手机app").start();
        new Thread(threadTest4,"电脑客户端").start();
    }
}

运行结果

在这里插入图片描述

模拟龟兔赛跑(案例)

package Test;
/**
 * Created by MR.ZHANG on 2020/7/31 16:42
 */
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(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //判断比赛是否结束
            Boolean flag = gameOver(i);
            if(flag){
                break;
            }
            System.out.println(Thread.currentThread().getName()+"->跑了 "+i+"米");
        }
    }
    //判断比赛是否结束
    public Boolean gameOver(int step){
        //判断是否有胜利者
        if(winner!=null){
            return true;
        }else {
            if (step>=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();
    }
}

结果
在这里插入图片描述

2.3 实现callable接口

在这里插入图片描述

package demo;
import Test.ThreadTest2;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.Callable;
/**
 * Created by MR.ZHANG on 2020/7/31 17:01
 */
//方式三,利用callable接口去实现多线程
public class CallableTest implements Callable<Boolean> {
    private String url;//网络图片的url
    private String name;//文件名字

    public CallableTest(String url,String name){
        this.url=url;
        this.name=name;
    }
    @Override
    public Boolean call() {
        webDownLoad downLoad = new webDownLoad();
        downLoad.download(url,name);
        System.out.println("下载了图片"+name);
        return true;
    }
   public static void main(String[] args) throws ExecutionException, InterruptedException {
        CallableTest callableTest = new CallableTest("https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1596178880&di=bdd01c5e3da4d69f38286754154454cc&src=http://img.yzt-tools.com/20190708/7bbf9da8ff29079c6f3f8e9e47d17b0b.jpg?x-oss-process=image/resize,w_600/auto-orient,1/quality,q_90/format,jpg", "1.jpg");
        CallableTest callableTest1 = new CallableTest("https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1596178880&di=bdd01c5e3da4d69f38286754154454cc&src=http://img.yzt-tools.com/20190708/7bbf9da8ff29079c6f3f8e9e47d17b0b.jpg?x-oss-process=image/resize,w_600/auto-orient,1/quality,q_90/format,jpg", "2.jpg");
        CallableTest callableTest2 = new CallableTest("https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1596178880&di=bdd01c5e3da4d69f38286754154454cc&src=http://img.yzt-tools.com/20190708/7bbf9da8ff29079c6f3f8e9e47d17b0b.jpg?x-oss-process=image/resize,w_600/auto-orient,1/quality,q_90/format,jpg", "3.jpg");

        //创建执行服务
        ExecutorService service = Executors.newFixedThreadPool(3);
        //提交执行
        Future<Boolean> r1 = service.submit(callableTest);
        Future<Boolean> r2 = service.submit(callableTest1);
        Future<Boolean> r3 = service.submit(callableTest2);
        //获取结果
        Boolean rs1 = r1.get();
        Boolean rs2 = r2.get();
        Boolean rs3 = r3.get();
        //关闭服务
        service.shutdownNow();
    }
}
class  webDownLoad {
    //下载方法
    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异常,download方法出现问题");
        }
    }
}

在这里插入图片描述

3 .静态代理

第一步
要有一个共同的接口
第二步
代理角色和真实角色必须实现同一个接口,代理角色实现需要的功能
第三步
创建真实角色的对象和代理角色的对象,并将真实角色对象的引用传给代理角色,让代理角色去执行功能
在这里插入图片描述`

package demo;
/**
 * Created by MR.ZHANG on 2020/7/31 17:22
 */
//静态代理模式
public class StaticProxy {
    public static void main(String[] args) {
        WeddingCompany company = new WeddingCompany(new You());
        company.marry();
    }
}
class You implements Marry{
    @Override
    public void marry() {
        System.out.println("今天你结婚了,你非常开心");
    }
}
interface Marry{
    void marry();
}
class  WeddingCompany implements Marry{
    private Marry marry;
    public WeddingCompany(Marry marry) {
        this.marry = marry;
    }
    @Override
    public void marry() {
        before();
        this.marry.marry();
        after();
    }
    private void after() {
        System.out.println("结婚之后我们要去结算尾款");
    }
    private void before() {
        System.out.println("结婚之前准备婚礼等一系列事务");
    }
}

在这里插入图片描述这里我们并没有new 一个You的实例,而是让第三方去代理,我们把You的对象传递进去由三方帮助我们实现。

4.lamda表达式

在这里插入图片描述在这里插入图片描述在这里插入图片描述

package com.zy.lamda;

/**
 * Created by MR.ZHANG on 2020/7/31 17:46
 */

/**
 * 逐步推导lamda表达式
 */
public class TestLamda {

    public static void main(String[] args) {
        ILike like = new like();
        like.lamda();
         like = new like2();
        like.lamda();



        //第三种局部内部类
        class like3 implements ILike {
            @Override
            public void lamda() {
                System.out.println("i like lamda maybe3");
            }
        }

        like =new like3();
        like.lamda();
        //第四种匿名内部类 ,没有类的名称,只需要继承父类的接口
        like = new ILike() {
            @Override
            public void lamda() {

                System.out.println("i like lamda maybe4");
            }
        };
        like.lamda();
        //使用lamda表达式
        like= ()->{
            System.out.println(" i like lamda mybe5");
        };
        like.lamda();

    }
   //第二种定义在内部类的
  static class like2 implements ILike {
       @Override
       public void lamda() {
           System.out.println("i like lamda maybe2");
       }
   }


}

//定义一个函数式接口
interface ILike{
    void lamda();
}

//第一种实现类
class like implements ILike {
    @Override
    public void lamda() {
        System.out.println("i like lamda maybe");
    }
}


在这里插入图片描述总结:lamda表达式只有在执行语句是一条的时候才能简化成一条语句以及去掉 花括号
在这里插入图片描述

5.线程五大状态

在这里插入图片描述
在这里插入图片描述

5.1线程方法

在这里插入图片描述在这里插入图片描述

package demo;

/**
 * Created by MR.ZHANG on 2020/7/31 19:49
 */

//测试stop
    //建议线程自动停止--》利用次数,不建议死循环
    //建议使用标志位数=--》去设置一个标志位

public class TestStop  implements Runnable{

    //设置一个标识位
    private boolean flag=true;

    @Override
    public void run() {
        int i=0;
        while(flag){
            System.out.println("run ++++");
        }

    }
    //设置一个公开的stop方法,转换标志位
    public void stop(){
        this.flag=false;
    }
    public static void main(String[] args){

        TestStop stop = new TestStop();
        new Thread(stop).start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("main"+i);
            if (i==900){
                stop.stop();
                System.out.println("线程停止了");
            }
        }
    }
}

在这里插入图片描述

5.2线程休眠

在这里插入图片描述

package demo;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
 * Created by MR.ZHANG on 2020/7/31 20:06
 */
//模拟倒计时操作
public class TestSleep2 implements Runnable {
    public static void main(String[] args) throws InterruptedException {
        
        Date startTime=new Date(System.currentTimeMillis());
        TestSleep2.tenDown();

        while(true){
            Thread.sleep(2000);
            System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
            startTime=new Date(System.currentTimeMillis());
        }
    }
    @Override
    public void run() {

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

5.3线程礼让

在这里插入图片描述

package demo;

/**
 * Created by MR.ZHANG on 2020/7/31 22:12
 */


public class TestYield  {

    public static void main(String[] args) {
        MyYield myYield = new MyYield();

        new Thread(myYield,"a").start();
        new Thread(myYield,"b").start();

    }

}
class MyYield implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"线程开始启动");
        Thread.yield();//礼让
        System.out.println(Thread.currentThread().getName()+"线程结束");
    }
}

在这里插入图片描述

5.4 join

在这里插入图片描述

package demo;

/**
 * Created by MR.ZHANG on 2020/7/31 22:22
 */

//测试join方法 ,想象为插队
public class TestJoin implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("vip来了,想要插队");
        }

    }
    public static void main(String[] args) throws InterruptedException {

        //启动我们的线程
        TestJoin testJoin = new TestJoin();

        Thread thread = new Thread(testJoin);
        thread.start();

        for (int i = 0; i < 1000; i++) {
            if (i==200){
                thread.join();
            }
            System.out.println("main"+i);
        }

    }

}


在这里插入图片描述

5.5 线程状态观察

在这里插入图片描述

package demo;

import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;

/**
 * Created by MR.ZHANG on 2020/7/31 22:35
 */


public class TestStatus {

    public static void main(String[] args) {

        Thread thread = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("///");
        });

        //观察状态
        Thread.State state=thread.getState();
        System.out.println(state);//NEW新生
        //观察启动后
        thread.start();
       state= thread.getState();
        System.out.println(state);//RUM

        while(state!= Thread.State.RUNNABLE){//只要线程不终止,就一直输出状态
            try {
                Thread.sleep(200);
                state=thread.getState();
                System.out.println(state);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

在这里插入图片描述

5.6线程的优先级

在这里插入图片描述代码测试

package demo;

/**
 * Created by MR.ZHANG on 2020/8/1 14:11
 */


public class TestPriority {
    public static void main(String[] args) {
        //主线程的优先级是默认的无法改变的
        System.out.println(Thread.currentThread().getName()+"--->"+Thread.currentThread().getPriority());

        MyPriority myPriority = new MyPriority();
        Thread thread = new Thread(myPriority);
        Thread thread1 = new Thread(myPriority);
        Thread thread2 = new Thread(myPriority);
        Thread thread3 = new Thread(myPriority);
        Thread thread4 = new Thread(myPriority);
        Thread thread5 = new Thread(myPriority);
        Thread thread6 = new Thread(myPriority);
        thread.start();
        thread1.start();
        //需要先默认设置优先级否则默认按优先级五来算
        thread2.setPriority(1);
        thread2.start();
        thread3.setPriority(2);
        thread3.start();
        thread4.setPriority(3);
        thread4.start();
        thread5.setPriority(4);
        thread5.start();
        thread6.setPriority(Thread.MAX_PRIORITY);
        thread6.start();
    }


}
class  MyPriority implements Runnable{

    @Override
    public void run() {

        System.out.println(Thread.currentThread().getName()+"--->"+Thread.currentThread().getPriority());
    }
}

在这里插入图片描述
在这里插入图片描述

5.7守护线程

在这里插入图片描述`

package Test;

import com.sun.org.apache.xml.internal.utils.ThreadControllerWrapper;

/**
 * Created by MR.ZHANG on 2020/8/1 14:50
 */


public class TestDaemon {

    public static void main(String[] args) {
        God god = new God();
        You you = new You();

        Thread thread = new Thread(god);
        thread.setDaemon(true);//将用户线程设置成守护线程,如果不设置true默认false用户进程
            //开启守护进程
        thread.start();
        new Thread(you).start();



    }
}
//上帝进程
class God implements Runnable{
    @Override
    public void run() {
        while (true){
            System.out.println("上帝保护着你");
        }

    }
}
//你
class You implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 36500; i++) {
            System.out.println("你已经开心的活着第 "+i+"天");
        }
        System.out.println("====goodbye! world===");
    }
}

在这里插入图片描述

5.8线程的同步

多个线程操作同一个资源
并发:
同一个对象被多线程操作

在这里插入图片描述在这里插入图片描述线程安全:要靠队列加锁来实现
线程同步
在这里插入图片描述

5.9三个场景模拟线程不安全

模拟买票

package com.zy.synchorized;

import com.sun.xml.internal.bind.v2.model.annotation.RuntimeAnnotationReader;

/**
 * Created by MR.ZHANG on 2020/8/1 15:10
 */

//不安全买票
public class UnSafeBuyTicket {
    public static void main(String[] args) {
        BuyTicket ticket = new BuyTicket();
        Thread a = new Thread(ticket, "黄牛");
        Thread b = new Thread(ticket, "苦逼的我");
        Thread c = new Thread(ticket, "苦逼的你");
        Thread d = new Thread(ticket, "脚本");
        a.start();
        b.start();
        c.start();
        d.start();
    }

}

class BuyTicket implements Runnable {

    private int ticketNus =20;
    Boolean flag=true;
    @Override
    public void run() {

        while (flag){
            buyTicket();
        }
    }

    public void buyTicket()  {

        if (ticketNus<=0){
            flag=false;
            return;
        }
        //模拟延时
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //买票
        System.out.println(Thread.currentThread().getName()+"买到了第 "+ticketNus--);
    }
}

在这里插入图片描述模拟银行取款

package com.zy.synchorized;

/**
 * Created by MR.ZHANG on 2020/8/1 15:26
 */

//不安全的银行取钱操作
public class UnSafeBank {
    public static void main(String[] args){
        Account account = new Account(100, "购房基金");

        Bank you = new Bank(account, 50, "你");
        Bank youGirlFriend = new Bank(account, 100, "你女朋友");

        you.start();
        youGirlFriend.start();
    }

}

//账户
class Account{
    int money;//余额
    String name;//卡名
    public Account(int money,String name){
        this.money=money;
        this.name=name;
    }
}
//银行
class Bank extends Thread{
    Account account;
    int drawMoney;//取了多少钱
    int nowMoney;//现在手里钱

    public Bank(Account account,int drawMoney,String name){
        super(name);
        this.account=account;
        this.drawMoney=drawMoney;
    }

    @Override
    public void run() {
        //判断有没有钱
        if (account.money-drawMoney<0){
            System.out.println(Thread.currentThread().getName()+"钱不够,取不了");
            return;
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //卡内余额等于你的钱减去取出来的钱
        account.money=account.money-drawMoney;
        //手里的钱
        nowMoney=nowMoney+drawMoney;
        System.out.println(account.name+"银行的余额"+account.money);
        System.out.println(Thread.currentThread().getName()+"手里的钱"+nowMoney);
    }
}

在这里插入图片描述不安全集合测试

package com.zy.synchorized;

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

/**
 * Created by MR.ZHANG on 2020/8/1 15:46
 */
public class UnsSafeList {
    public static void main(String[] args) {
        List arrayList= new ArrayList<String>();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
               arrayList.add(Thread.currentThread().getName());
            }).start();
        }
        System.out.println(arrayList.size());
    }//运行结果应该是10000可是这里并不是一万![在这里插入图片描述](https://img-blog.csdnimg.cn/20200801160009934.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NvZGluZ2xvdmVyNQ==,size_16,color_FFFFFF,t_70)

}

在这里插入图片描述

5.10 线程安全

在这里插入图片描述同步代码块
在这里插入图片描述sychronized关键字
synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:

  1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
public void run() {
        //锁的对象是曾删改的对象
        synchronized (account){
            //判断有没有钱
            if (account.money-drawMoney<0){
                System.out.println(Thread.currentThread().getName()+"钱不够,取不了");
                return;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //卡内余额等于你的钱减去取出来的钱
            account.money=account.money-drawMoney;
            //手里的钱
            nowMoney=nowMoney+drawMoney;
            System.out.println(account.name+"银行的余额"+account.money);
            System.out.println(Thread.currentThread().getName()+"手里的钱"+nowMoney);

        }
  1. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
 public synchronized void buyTicket()  {
        if (ticketNus<=0){
            flag=false;
            return;
        }
        //模拟延时
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //买票
        System.out.println(Thread.currentThread().getName()+"买到了第 "+ticketNus--);
    }
  1. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
/**
* 同步线程
*/
class SyncThread implements Runnable {
        private static int count;

        public SyncThread() {
            count = 0;
        }

        public synchronized static void method() {
            for (int i = 0; i < 5; i ++) {
                try {
                    System.out.println(Thread.currentThread().getName() + ":" + (count++));
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        public synchronized void run() {
            method();
        }
}
  1. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

JUC安全类测试

package com.zy.synchorized;

import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;

/**
 * Created by MR.ZHANG on 2020/8/1 16:40
 */


public class TestJUC {
    public static void main(String[] args) {
        CopyOnWriteArrayList<String> list =new CopyOnWriteArrayList();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                list.add(Thread.currentThread().getName());
            }).start();
        }
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

6 死锁

在这里插入图片描述在这里插入图片描述

package com.zy.Lock;

/**
 * Created by MR.ZHANG on 2020/8/1 16:49
 */

//死锁:两个线程互相持有对方需要的资源,然后形成僵持,
public class DeadLock {
    public static void main(String[] args) {
        MakeUp up = new MakeUp(0, "白雪公主");
        MakeUp up1 = new MakeUp(1, "灰姑凉");
        up.start();
        up1.start();
    }
}
//口红类
class LipStick{

}
//镜子类
class Mirror{

}
class MakeUp extends Thread{

    //一份资源用static,来表示这些资源只有一分
    static LipStick lipStick=new LipStick();
    static Mirror mirror=new Mirror();

    int choice;//悬着
    String girlName;//选择化妆品的人

    MakeUp(int choice,String girlName){
        this.choice=choice;
        this.girlName=girlName;
    }
    @Override
    public void run() {
        try {
            makeUp();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public void makeUp() throws InterruptedException {

        if(choice==0){
            synchronized (lipStick){
                System.out.println(girlName+"拿到了口红锁");
            }
            Thread.sleep(1000);
            synchronized (mirror){
                System.out.println(girlName+"拿到了镜子的锁");
            }
        }else{
            synchronized (mirror){
                System.out.println(girlName+"拿到了镜子锁");
            }
            Thread.sleep(2000);
            synchronized (lipStick){
                System.out.println(girlName+"拿到了口红的锁");
            }
        }


        }

}

6.1lock锁

在这里插入图片描述
常用的是ReentrantLock 可重用锁

package com.zy.Lock;

import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl;

import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by MR.ZHANG on 2020/8/1 17:10
 */


public class TestLock {
    public static void main(String[] args) {
        TestLock2 lock2 = new TestLock2();
        Thread t1 = new Thread(lock2,"A");
        Thread t2 = new Thread(lock2,"B");
        Thread t3 = new Thread(lock2,"C");
        t1.start();
        t2.start();
        t3.start();
    }

}
class TestLock2 implements Runnable{
    private ReentrantLock lock =new ReentrantLock();
    private int ticketNums=20;
    @Override
    public void run() {
        try {
            lock.lock();//加锁
            while (true){
                if (ticketNums>0){
                    System.out.println(Thread.currentThread().getName()+"--"+ticketNums--);
                }else {
                    break;
                }

            }
        }finally {
            lock.unlock();
        }

    }
}

在这里插入图片描述在这里插入图片描述

7.线程协作

生产者消费者模式
线程通信
在这里插入图片描述在这里插入图片描述在这里插入图片描述

解决方式一 管程法

在这里插入图片描述

package com.zy.Lock;

/**
 * Created by MR.ZHANG on 2020/8/1 17:51
 */

//测试:生产者消费者模型,利用缓冲区解决:管程法

    //生产者,消费者,产品,缓冲区
public class TestPc {
    public static void main(String[] args) {
        SysContainer container = new SysContainer();
        new Provider(container).start();
        new Customer(container).start();
    }

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

        }
    }
}
//消费者
class Customer extends Thread{
    SysContainer container;
    public Customer(SysContainer container){
        this.container=container;
    }
//消费
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {

            System.out.println("消费了" +container.pop().id+"只鸡");
        }
    }
}
//产品
class Chicken{
    int id;

    public Chicken(int id) {
        this.id = id;
    }
}
class SysContainer{
    //需要一个容器大小

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

    //消费者消费产品
    public synchronized Chicken pop(){
        //判断内否消费
        if(count==0){
            //等待生产者生产,消费者等待
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //如果可以消费
        count--;
        Chicken chicken = chickens[count];
        //吃完了通知生产者生产
        this.notifyAll();
        return chicken;
    }

}

在这里插入图片描述

解决方式二 信号灯法

在这里插入图片描述

package com.zy.PC;
/**
 * Created by MR.ZHANG on 2020/8/1 19:38
 */
//测试生产者消费问题;信号灯法,标志位解决
public class TestPC2 {
    public static void main(String[] args) {

        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("天天向上");
            }
        }
    }
}
//观众
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;//表演的节目
    //演员表演节目观众等待  T
    //观众观看时,演员等待   F
    Boolean flag=true;
    //表演
public synchronized void play(String voice){
    if (!flag){
        try {
            this.wait();
        } catch (InterruptedException 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 (InterruptedException e) {
            e.printStackTrace();
        }
    }
        System.out.println("观看完了"+voice);
    //通知演员继续表演
        this.notifyAll();
        this.flag=!this.flag;
    }
}

在这里插入图片描述

8 线程池

在这里插入图片描述在这里插入图片描述

package com.zy.PC;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by MR.ZHANG on 2020/8/1 19:58
 */

//测试线程池
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());
        //2.关闭连接
		service.shutdown();
    }
}
class MyThread implements Runnable{
    @Override
    public void run() {
            System.out.println(Thread.currentThread().getName());

    }
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值