多线程学习

多线程学习

线程简介

程序------进程-------线程

  1. 线程是独立执行的路径

  2. 在程序运行中,即使没有自己创建线程,后台也会有多个线程,如主线程(main)\线程

  3. main()称为主线程,是程序的入口,用于执行整个程序

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

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

  6. 线程对带来额外的开销,如cpu调度时间,并发控制开销

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

线程创建

Thread、Runnable接口、Callable接口

继承Thread

  1. 自定义线程继承Thread类

  2. 重写 run()方法,编写线程执行体

  3. 创建线程对象,调用start()方法启动线程

package com.tan;
// 创建线程方式:继承Thread类,重写run()方法,调用start()开启线程
// 注意:线程开启不一定立即执行,由cpu调度
public class TestThread1 extends Thread{
    @Override
    public void run() {
        // run()方法线程体
        for (int i = 0; i < 10; i++) {
            System.out.println("我再看代码===="+i);
        }
    }
​
    public static void main(String[] args) {
        // main线程,主线程
​
        //创建一个线程对象
        TestThread1 testThread1= new TestThread1();
        // 调用start()方法开启线程
        testThread1.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("我在学习多线程==="+i);
        }
    }
}
package com.gentlesoft.oa.archives.controller;
​
import com.gentlesoft.oa.util.FileUtil;
import org.apache.commons.io.FileUtils;
import org.apache.poi.xwpf.usermodel.IRunBody;
​
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
​
public class Person extends Thread{
    // 联系Thread,实现多线程同步下载图片
    private String url;
    private String name ;
​
    public Person(String url,String name){
        this.url  = url;
        this.name = name;
    }
    @Override
    public void run() {
        WebDownLoader webDownLoader = new WebDownLoader();
        try {
            webDownLoader.downloader(url,name);
            System.out.println("下载了 图片:"+name);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
​
    public static void main(String[] args) {
        Person p3 = new Person("https://image.so.com/view?q=%E5%9B%BE%E7%89%87&listsrc=sobox&listsign=9f3a1eeb2c9fe66d36e55cf51f4b33ae&src=360pic_new_strong&correct=%E5%9B%BE%E7%89%87&ancestor=list&cmsid=91fe43da94b3ac037ee2da957a90d6f9&cmras=0&cn=0&gn=0&kn=49&crn=0&bxn=20&fsn=129&cuben=0&pornn=0&manun=24&adstar=0&clw=284#id=9f3a1eeb2c9fe66d36e55cf51f4b33ae&currsn=0&ps=101&pc=101","111");
        Person p1 = new Person("https://image.so.com/view?q=%E5%9B%BE%E7%89%87&listsrc=sobox&listsign=9f3a1eeb2c9fe66d36e55cf51f4b33ae&src=360pic_new_strong&correct=%E5%9B%BE%E7%89%87&ancestor=list&cmsid=91fe43da94b3ac037ee2da957a90d6f9&cmras=0&cn=0&gn=0&kn=49&crn=0&bxn=20&fsn=129&cuben=0&pornn=0&manun=24&adstar=0&clw=284#id=9f3a1eeb2c9fe66d36e55cf51f4b33ae&currsn=0&ps=101&pc=101","222");
        Person p2 = new Person("https://image.so.com/view?q=%E5%9B%BE%E7%89%87&listsrc=sobox&listsign=9f3a1eeb2c9fe66d36e55cf51f4b33ae&src=360pic_new_strong&correct=%E5%9B%BE%E7%89%87&ancestor=list&cmsid=91fe43da94b3ac037ee2da957a90d6f9&cmras=0&cn=0&gn=0&kn=49&crn=0&bxn=20&fsn=129&cuben=0&pornn=0&manun=24&adstar=0&clw=284#id=9f3a1eeb2c9fe66d36e55cf51f4b33ae&currsn=0&ps=101&pc=101","333");
​
        p3.start();
        p1.start();
        p2.start();
    }
​
}
​
//下载器
class WebDownLoader{
    // 下载方法
    public void downloader(String url,String name) throws IOException {
        try {
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO异常,下载方法出现问题");
        }
    }
}

实现runnable接口

  1. 创建线程类实现Runnable接口

  2. 重写 run()方法,编写线程执行体

  3. 创建线程对象,调用start()方法启动线程

package com.gentlesoft.oa.archives.controller;
// 创建线程方法2:实现Runnable接口,重写run方法,执行线程需要丢入Runnable接口实现类,调用start方法
public class Person implements Runnable {
​
    @Override
    public void run() {
        // run()方法线程体
        for (int i = 0; i < 10; i++) {
            System.out.println("我再看代码===="+i);
        }
    }
    public static void main(String[] args) {
        //创建runnable接口的实现类对象
        Person person = new Person();
        // 创建线程对象,通过线程对象来开启我们的线程
        Thread thread = new Thread(person);
        thread.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("我在学习===="+i);
        }
    }
}

初始并发

package com.gentlesoft.oa.archives.controller;
// 多个线程实现同时操作一个类
// 买火车票的例子
​
// 发现问题:多个线程操作同一个资源的情况下,线程不安全
public class Person implements Runnable {
    // 票数
    private int ticktNums = 10;
    @Override
    public void run() {
        while(true){
            if (ticktNums<=0){
                break;
            }
            // 模拟延迟
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"---->拿到了第"+ticktNums--+"张票");
        }
    }
​
    public static void main(String[] args) {
        Person person = new Person();
        new Thread(person,"小明").start();
        new Thread(person,"胡").start();
        new Thread(person,"小拜拜").start();
    }
}

案例:龟兔赛跑

package com.gentlesoft.oa.archives.controller;
​
public class Race implements Runnable{
    // 胜利者
    private static String winner;
    @Override
    public void run() {
​
        for (int i = 0; i <= 100; i++) {
            // 模拟兔子休息
            if(Thread.currentThread().getName()=="兔子"){
                try {
                    Thread.sleep(15);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // 判断比赛是否结束
            boolean flag = gameOver(i);
            if(flag==true){
                // 如果比赛结束 停止程序
                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接口

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

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

  3. 创建目标对象

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

  5. 提交执行:Future<Bollean> result = ser.submit(t1);

  6. 获取结果:boolean r1= result.get();

  7. 关闭服务:ser.shutdownNow():

package com.gentlesoft.oa.archives.controller;
​
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<Boolean> {
    // 联系Thread,实现多线程同步下载图片
    private String url;
    private String name ;
​
    public TestCallable(String url,String name){
        this.url  = url;
        this.name = name;
    }
    @Override
    public Boolean call() throws IOException {
        WebDownLoader webDownLoader = new WebDownLoader();
        try {
            webDownLoader.downloader(url,name);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("下载了 图片:"+name);
            return true;
    }
​
    public static void main(String[] args) throws ExecutionException,InterruptedException {
        TestCallable p1 = new TestCallable("https://p1.ssl.qhimg.com/t01e2198cad53ecdf1b.jpg","1.jpg");
        TestCallable p2 = new TestCallable("https://p1.ssl.qhimg.com/t01e2198cad53ecdf1b.jpg","2.jpg");
        TestCallable p3 = new TestCallable("https://p1.ssl.qhimg.com/t01e2198cad53ecdf1b.jpg","3.jpg");
​
        // 创建执行服务
        ExecutorService ser = Executors.newFixedThreadPool(3);
        // 提交执行
        Future<Boolean> r1 = ser.submit(p1);
        Future<Boolean> r2 = ser.submit(p2);
        Future<Boolean> r3 = ser.submit(p3);
        // 获取结果
        boolean rs1 = r1.get();
        boolean rs2 = r2.get();
        boolean rs3 = r3.get();
        System.out.println(rs1);
        System.out.println(rs2);
        System.out.println(rs3);
​
        // 关闭服务
        ser.shutdownNow();
    }
​
}
​
//下载器
class WebDownLoader{
    // 下载方法
    public void downloader(String url,String name) throws IOException {
        try {
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO异常,下载方法出现问题");
        }
    }
}

静态代理

package com.gentlesoft.oa.archives.controller;
//静态 代理模式
// 真实对象和代理对象都要实现同一个接口
// 代理对象代理真实角色
// 好处:
    // 代理对象可以做很多真实对象做不了的事情
    // 真实对象专注自己的事情
public class TestCallable  {
​
    public static void main(String[] args) {
        // 多线程方式
        new Thread(()-> System.out.println("我爱你")).start();
        You you = new You();
        // 代理模式
        /*WeddingCompany  weddingCompany = new WeddingCompany(you);
        weddingCompany.HappyMarry();*/
        new WeddingCompany(new You()).HappyMarry();
    }
}
interface Marry{
void HappyMarry();
}
// 真实结婚的角色You
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("结婚之前布置会场");
    }
}

Lamda表达式

package com.gentlesoft.oa.archives.controller;
​
public class TestLamda {
    //3.静态内部类
    static class Like2 implements ILike{
        @Override
        public void Lamda() {
            System.out.println("i like lamda2");
        }
    }
    public static void main(String[] args) {
        ILike like = new Like();
        like.Lamda();
​
        like = new Like2();
        like.Lamda();
​
        // 4.局部内部类
        class Like3 implements ILike{
            @Override
            public void Lamda() {
                System.out.println("i like lamda3");
            }
        }
        like = new Like3();
        like.Lamda();
        // 5. 匿名内部类
        like = new ILike() {
            @Override
            public void Lamda() {
                System.out.println("i like lamda4");
            }
        };
        like.Lamda();
        // 6.lamda 表达式简化
        like = ()->{
            System.out.println("i like lamda5");
        };
        like.Lamda();
    }
}
// 1.定义函数式接口
interface ILike{
    void Lamda();
}
//2.实现类
class Like implements ILike{
​
    @Override
    public void Lamda() {
        System.out.println("i like lamda");
    }
}
​

线程停止

package com.gentlesoft.oa.archives.controller;
// 测试stop
// 1.建议线程正常停止-->利用次数,不建议死循环
// 2.建议使用标志位--->设置一个标志
// 3.不要使用stop/destory等过时或者JDK不建议使用的方法
public class Race implements Runnable{
    // 1.设置一个标志
    private boolean flag= true;
​
    @Override
    public void run() {
        int i= 0;
        while(flag){
        System.out.println("run.....Thread"+i++);
        }
    }
    // 设置一个公开的方法停止线程,转换标志位
    public void stop(){
        this.flag = false;
    }
    public static void main(String[] args) {
        Race teststop = new Race();
        new Thread(teststop).start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("main主线程:"+i);
            if (i==900){
                // 调用stop方法让线程停止
                teststop.stop();
                System.out.println("该线程停止了");
            }
        }
    }
}

线程休眠

package com.gentlesoft.oa.archives.controller;
​
import java.text.SimpleDateFormat;
import java.util.Date;
​
// 模拟网络延时:方法问题的发生性
// 模拟倒计时
public class Race {
    public static void tenDown() throws InterruptedException {
        int num = 10;
        while (true) {
            Thread.sleep(1000);
            System.out.println(num--);
            if (num <= 0) {
                break;
            }
        }
    }
​
    public static void main(String[] args) throws InterruptedException {
       /* try {
            tenDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }*/
        Date startTime = new Date(System.currentTimeMillis());//获取系统当前时间
        while (true) {
            Thread.sleep(1000);
            System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
            startTime = new Date(System.currentTimeMillis());//更新当前时间
        }
​
    }
}

线程礼让

package com.gentlesoft.oa.archives.controller;
​
// 测试礼让线程
// 礼让不一定成功,看CPU心情
public class Race {
    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()+"线程停止执行");
    }
}

线程强制执行join(插队)

package com.gentlesoft.oa.archives.controller;
​
// 测试join方法
public class Race implements Runnable{
​
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("线程vip来了"+i);
        }
    }
​
​
    public static void main(String[] args) throws InterruptedException {
     // 启动线程
        Race race =  new Race();
        Thread thread = new Thread(race);
        thread.start();
        // 主线程
        for (int i = 0; i < 1000; i++) {
            if(i==200){
                thread.join();
            }
            System.out.println("main:"+i);
        }
    }
}

检测线程的状态

package com.gentlesoft.oa.archives.controller;
​
// 观测线程状态
public class Race {
    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);
        // 观察启动后
        thread.start();
        state = thread.getState();
        System.out.println(state);
        while(state!=Thread.State.TERMINATED){// 只要线程不停止,就一直输出状态
            Thread.sleep(1000);
            state = thread.getState();// 更新线程状态
            System.out.println(state);
        }
    }
}

线程的优先级--用数字表示

getPriority()

setPriority(int xxx)

package com.gentlesoft.oa.archives.controller;
// 测试线程的优先级
public class Race {
    public static void main(String[] args) {
        // 主线程的优先级
        System.out.println(Thread.currentThread().getName()+"---->"+Thread.currentThread().getPriority());
        Mypriority mypriority = new Mypriority();
        Thread t1= new Thread(mypriority);
        Thread t2= new Thread(mypriority);
        Thread t3= new Thread(mypriority);
        Thread t4= new Thread(mypriority);
        // 设置优先级,在启动
        t1.start();
        t2.setPriority(1);
        t2.start();
        t3.setPriority(4);
        t3.start();
        t4.setPriority(Thread.MAX_PRIORITY);
        t4.start();
    }
}
​
class Mypriority implements Runnable{
​
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"---->"+Thread.currentThread().getPriority());
    }
}

守护线程

package com.gentlesoft.oa.archives.controller;
// 测试守护线程
public class Race {
    public static void main(String[] args) {
        God god = new God();
        You you = new You();
        Thread thread = new Thread(god);
        thread.setDaemon(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("一生都很开心");
        }
        System.out.println("=======googbye world=====");
    }
}

线程同步

不安全情况

package com.gentlesoft.oa.archives.controller;
// 不安全的买票
// 线程不安全 有负数
public class Race {
    public static void main(String[] args) {
        BuyTicket station = new BuyTicket();
​
        new Thread(station,"一号主要人员").start();
        new Thread(station,"二号主要人员").start();
        new Thread(station,"三号主要人员").start();
    }
}
class BuyTicket implements Runnable{
    //票
    private int ticketNums = 10;
    boolean flag = true;//外部停止方式
    @Override
    public void run() {
        // 买票
        while(flag){
            try {
                buy();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    private void buy() throws InterruptedException {
        // 判断是否邮票
        if(ticketNums<=0){
            flag=false;
            return;
        }
        // 模拟延迟
        Thread.sleep(100);
        // 买票
        System.out.println(Thread.currentThread().getName()+"买到"+ticketNums--);
    }
​
}
package com.gentlesoft.oa.archives.controller;
// 不安全的取钱
// 两个人去银行取钱,账户
public class Race {
    public static void main(String[] args) {
        Account account = new Account(100,"结婚基金");
        Drawing you = new Drawing(account,50,"你");
        Drawing gilefriend = new Drawing(account,100,"女朋友");
        you.start();
        gilefriend.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;
        this.nowMoney = nowMoney;
    }
    // 取钱
    @Override
    public void run() {
        if(account.money-drawingMoney<0){
            System.out.println(Thread.currentThread().getName()+"账户余额不足");
            return;
        }
        // sleep可以放大问题的发生性
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //卡内余额 = 余额-取的钱
        account.money = account.money-drawingMoney;
        // 手里的钱
        nowMoney = nowMoney + drawingMoney;
        System.out.println(account.name+"账户余额为:"+account.money);
        System.out.println(account.name+"手里余额为:"+nowMoney);
    }
}

同步块

package com.gentlesoft.oa.archives.controller;
// 不安全的买票
// 线程不安全 有负数
public class Race {
    public static void main(String[] args) {
        BuyTicket station = new BuyTicket();
​
        new Thread(station,"一号主要人员").start();
        new Thread(station,"二号主要人员").start();
        new Thread(station,"三号主要人员").start();
    }
}
class BuyTicket implements Runnable{
    //票
    private int ticketNums = 10;
    boolean flag = true;//外部停止方式
    @Override
    public void run() {
        // 买票
        while(flag){
            try {
                buy();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    // synchronized 同步方法,锁的是this
    private synchronized void buy() throws InterruptedException {
        // 判断是否邮票
        if(ticketNums<=0){
            flag=false;
            return;
        }
        // 模拟延迟
        Thread.sleep(100);
        // 买票
        System.out.println(Thread.currentThread().getName()+"买到"+ticketNums--);
    }
​
}
package com.gentlesoft.oa.archives.controller;
// 不安全的取钱
// 两个人去银行取钱,账户
public class Race {
    public static void main(String[] args) {
        Account account = new Account(100,"结婚基金");
        Drawing you = new Drawing(account,50,"你");
        Drawing gilefriend = new Drawing(account,100,"女朋友");
        you.start();
        gilefriend.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;
        this.nowMoney = nowMoney;
    }
    // 取钱
    @Override
    public void run() {
        // 锁的对象就是变化的变量,锁的是增删改
        synchronized (account){
            if(account.money-drawingMoney<0){
                System.out.println(Thread.currentThread().getName()+"账户余额不足");
                return;
            }
            // sleep可以放大问题的发生性
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //卡内余额 = 余额-取的钱
            account.money = account.money-drawingMoney;
            // 手里的钱
            nowMoney = nowMoney + drawingMoney;
            System.out.println(account.name+"账户余额为:"+account.money);
            System.out.println(account.name+"手里余额为:"+nowMoney);
        }
​
​
    }
}

死锁

package com.gentlesoft.oa.archives.controller;
​
import org.apache.poi.ss.formula.functions.Mirr;
​
// 死锁:多个线程互相抱着对方需要的资源,然后形成僵持
public class DeadLock {
    public static void main(String[] args) {
        Makeup g1 = new Makeup(0,"灰姑娘");
        Makeup g2 = new Makeup(1,"白雪公主");
        g1.start();
        g2.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();
        }
    }
    // 化妆,互相持有方的锁,就是需要拿到对方的资源
    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){//一秒钟后获得镜子
                    System.out.println(this.girlName+"获得口红的锁");
                }
​
        }
    }
​
}
​

image-20220801110538112

Lock(锁)

ReentrantLock (可重入锁)实现了Lock

package com.gentlesoft.oa.archives.controller;
​
import java.util.concurrent.locks.ReentrantLock;
​
//测试Lock锁
public class TestLock {
        public static void main(String[] args) {
                TestLock2 testLock2 = new TestLock2();
​
                new Thread(testLock2).start();
                new Thread(testLock2).start();
                new Thread(testLock2).start();
        }
        }
class TestLock2 implements  Runnable{
        int tickNums = 10;
        // 定义lock锁
        private final  ReentrantLock lock = new ReentrantLock();
        @Override
        public void run() {
                while(true){
​
                        try {
                                lock.lock();// 加锁
                                if(tickNums>0){
                                        System.out.println(tickNums--);
                                        try {
                                                Thread.sleep(1000);
                                        } catch (InterruptedException e) {
                                                e.printStackTrace();
                                        }
                                }else{
                                        break;
                                }
                        }finally {
                              // 解锁
                              lock.unlock();
                        }
​
                }
        }
}

生产者消费者模式(问题)

解决方式1、

package com.gentlesoft.oa.archives.controller;
​
import java.util.concurrent.locks.ReentrantLock;
​
// 测试: 生产者消费者模型---> 利用缓冲区解决:管程法
// 生产者、消费者 产品 、 缓冲区
public class TestPC{
        public static void main(String[] args) {
                SynContainer container = new SynContainer();
                new Productor(container).start();
                new Customer(container).start();
​
        }
}
// 生产者
class Productor extends Thread{
        SynContainer container;
        public Productor(SynContainer 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{
        SynContainer container;
        public Customer(SynContainer 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 SynContainer{
        // 需要一个容器大小
        Chicken[] chickens = new Chicken[10];
        // 容器计数器
        int count = 0;
        // 生产者放入产品
        public synchronized void push(Chicken chicken){
                // 如果容器满了要等待消费者消费
                if(count==chickens.length){
                // 通知消费者消费,生产等待
                }
                // 没有满,需要丢入产品
                chickens[count] = chicken;
                count++;
                // 可以通知消费者消费了
        }
        // 消费者消费产品
        public  synchronized Chicken  pop(){
                // 判断能否此消费
                if(count==0){
                        // 等待生产者生产,消费者消费
                }
                // 如果可以消费
                count--;
                Chicken chicken   = chickens[count];
                // 吃完了 ,  通知生产者生产
                return chicken;
        }
​
}
​
package com.gentlesoft.oa.archives.controller;
​
import org.apache.poi.ss.formula.functions.T;
​
//测试生产者消费者问题2:信号灯法,标志位解决
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 ; // 表演的节目
    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;
    }
}

使用线程池

package com.gentlesoft.oa.archives.controller;
​
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
​
// 测试线程池
public class TestPC2 {
    public static void main(String[] args) {
        // 1.创建服务,创建线程池
        // newFixedThreadPool 参数为:
        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());
​
    }
}
posted @ 2022-08-01 17:53  重新study谭大叔  阅读(37)  评论(0)    收藏  举报