多线程

一、线程简介

  • 程序—进程—线程
  • 线程就是独立的执行的路径。即使没有创建线程,后台也会有主线程和GC线程等。
  • main()称为主线程。
  • 在一个进程中,如果开辟多个线程,线程的运行由调度器安排调度。
  • 线程会带来额外的开销,如CPU调度时间,并发控制开销。
  • 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致。

二、线程实现(重点)

Thread

  • 自定义线程类继承Thread类
  • 重写run()方法
  • 调用start开启线程
  • 注意:线程开启不一定立即执行。
  • 不建议使用:避免OOP单继承局限性
/**
 * Author:ckvsok
 * Date:2021/3/14
 **/

package thread;

public class Demo1 extends Thread{
    public static void main(String[] args) {
        Demo1 demo1 = new Demo1();
        //开启线程
        demo1.start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("我是主线程======="+i);
        }
    }

    @Override//重写run方法
    public void run() {
        for (int i = 0; i < 500; i++) {
            System.out.println("我是线程2-------------" +i);
        }
    }
}

多线程图片下载

/**
 * Author:ckvsok
 * Date:2021/3/15
 **/

package thread;

import org.apache.commons.io.FileUtils;

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

public class Demo2 extends Thread {
    private String url;
    private String name;

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

    @Override
    public void run() {
        WebDownloader webDownloader = new WebDownloader();
        webDownloader.downloader(url, name);
        System.out.println("下载的文件名为:" + name);
    }

    public static void main(String[] args) {
        Demo2 demo2_1 = new Demo2(
                "https://img-blog.csdnimg.cn/20210304092856208.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzUzMzAxNjM3,size_16,color_FFFFFF,t_70",
                "pic1.png");
        Demo2 demo2_2 = new Demo2(
                "https://img-blog.csdnimg.cn/20210304092856208.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzUzMzAxNjM3,size_16,color_FFFFFF,t_70",
                "pic2.png");
        Demo2 demo2_3 = new Demo2(
                "https://img-blog.csdnimg.cn/20210304092856208.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzUzMzAxNjM3,size_16,color_FFFFFF,t_70",
                "pic3.png");
        demo2_1.start();
        demo2_2.start();
        demo2_3.start();
    }

    //下载器
    class WebDownloader {
        public void downloader(String url, String name) {
            try {
                FileUtils.copyURLToFile(new URL(url), new File(name));
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("IO异常,downloader方法出现异常");
            }
        }
    }

}

Runnable

  • 定义MyRunnable类实现Runnable接口
  • 实现run()方法,编写线程执行体
  • 创建线程对象,传入Runnable接口实现类,调用start()方法启动线程
  • 推荐使用:避免了单继承局限性,灵活方便,方便同一个对象被多个线程使用
/**
 * Author:ckvsok
 * Date:2021/3/15
 **/

package thread;

public class Demo3  implements  Runnable{
    public static void main(String[] args) {
        //实现Runnable接口,实例化
        Demo3 demo3 = new Demo3();
        //创建Thread 传入Runnable接口实现类
        Thread thread = new Thread(demo3);
        //开启线程
        thread.start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("我是主线程======="+i);
        }
    }

    @Override//重写run方法
    public void run() {
        for (int i = 0; i < 500; i++) {
            System.out.println("我是线程2-------------" +i);
        }
    }
}

多个线程同时操作1个对象

买火车票的例子;出现了线程不安全的问题。

/**
 * Author:ckvsok
 * Date:2021/3/15
 **/

package thread;
//模拟抢票
public class Demo4 implements Runnable {
    private int ticketNum = 10;

    @Override
    public void run() {
        while (true){
            if (ticketNum<=0){
                break;
            }
            //模拟延时
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "抢到了倒数第" + ticketNum-- +"张票");

        }
    }

    public static void main(String[] args) {
        Demo4 ticket = new Demo4();
        //同时抢票
        new Thread(ticket,"A").start();
        new Thread(ticket,"B").start();
        new Thread(ticket,"C").start();
    }
}
结果:
B抢到了倒数第10张票
A抢到了倒数第9张票
C抢到了倒数第8张票
A抢到了倒数第7张票
B抢到了倒数第6张票
C抢到了倒数第7张票
A抢到了倒数第4张票
B抢到了倒数第4张票
C抢到了倒数第5张票
C抢到了倒数第3张票
B抢到了倒数第3张票
A抢到了倒数第2张票
C抢到了倒数第1张票
A抢到了倒数第1张票
B抢到了倒数第0张票

模拟龟兔赛跑

/**
 * Author:ckvsok
 * Date:2021/3/16
 **/

package thread;

//模拟龟兔赛跑
public class Demo5 implements Runnable{
    private static String winner;
    //赛道
    @Override
    public void run() {
        //模拟赛跑
        for (int i = 0; i <=100 ; i++) {
            //模拟兔子休息
            if (Thread.currentThread().getName().equals("兔子") && i/10==1){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //如果比赛结束了,就不用跑了
            if (gameOver(i)){
                break;
            }
            System.out.println(Thread.currentThread().getName() + "跑了"+i+"步");
        }
    }

    public static void main(String[] args) {
        //一条赛道,兔子和乌龟一起跑
        Demo5 race = new Demo5();
        new Thread(race,"兔子").start();
        new Thread(race,"乌龟").start();
    }

    //判断比赛结束
    public Boolean gameOver(int step){
        //判断是否存在胜利者
        if (winner != null){
            return true;
        }
        if (step == 100){
            winner = Thread.currentThread().getName();
            System.out.println("最终胜利者是:" + winner);
            return true;
        }
        return false;
    }
}

Callable

  • 实现,重写call方法,带返回值
  • 创建执行服务
  • 提交执行
  • 返回结果
  • 关闭服务
/**
 * Author:ckvsok
 * Date:2021/3/17
 **/

package thread;

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 Demo6 implements Callable
{

    private String url;
    private String name;

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

    @Override
    public Boolean call() throws Exception {
        WebDownloader webDownloader = new WebDownloader();
        webDownloader.downloader(url,name);
        System.out.println("下载的文件名为:" + name);
        return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Demo6 t1= new Demo6(
                "https://img-blog.csdnimg.cn/20210304092856208.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzUzMzAxNjM3,size_16,color_FFFFFF,t_70",
                "pic1.png");
        Demo6 t2 = new Demo6(
                "https://img-blog.csdnimg.cn/20210304092856208.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzUzMzAxNjM3,size_16,color_FFFFFF,t_70",
                "pic2.png");
        Demo6 t3 = new Demo6(
                "https://img-blog.csdnimg.cn/20210304092856208.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzUzMzAxNjM3,size_16,color_FFFFFF,t_70",
                "pic3.png");
        //创建执行服务
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        //提交执行
        Future<Boolean> r1 = executorService.submit(t1);
        Future<Boolean> r2 = executorService.submit(t2);
        Future<Boolean> r3 = executorService.submit(t3);
        //返回结果
        Boolean rs1 = r1.get();
        Boolean rs2 = r1.get();
        Boolean rs3 = r1.get();
        //关闭服务

    }

    //下载器
    class WebDownloader {
        public void downloader(String url, String name) {
            try {
                FileUtils.copyURLToFile(new URL(url), new File(name));
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("IO异常,downloader方法出现异常");
            }
        }
    }
}

静态代理

/**
 * Author:ckvsok
 * Date:2021/3/17
 **/

package thread;

//静态代理 例子:我,婚庆公司,结婚
public class Demo7 {

    public static void main(String[] args) {
        //被代理对象
        Me me = new Me();
        //代理对象
        Company company = new Company(me);
        company.happyMarry();
    }
}

    //定义接口,结婚
    interface Marry{
        //结婚方法
        void happyMarry();
    }
    //定义我,实现结婚接口
    class Me implements Marry{

        @Override
        public void happyMarry() {
            System.out.println("ck结婚了,超级开心");
        }
    }
    //定义婚庆公司,实现结婚接口,代理类
    class Company implements Marry{
        //定义被代理对象
        private Marry target;

        public Company(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 表达式

  • 实质属于函数式编程的概念
  • 函数式接口:一个接口,只含一个抽象方法
  • 减少内部类定义
  • 实现接口的对象

接口的实现

/**
 * Author:ckvsok
 * Date:2021/3/17
 **/

package thread;

//lambda表达式演变
public class Demo8 {
    public static void main(String[] args) {
        //1、接口实现类
        ILike like1 = new Like1();
        like1.like("a");
        //2、静态内部类
        ILike like2 = new Like2();
        like2.like("b");
        //3、局部内部类
        class Like3 implements ILike{

            @Override
            public void like(String name) {
                System.out.println(name +"->like");
            }
        }
        ILike like3 = new Like3();
        like3.like("c");
        //4、匿名内部类
        ILike like4 = new ILike() {
            @Override
            public void like(String name) {
                System.out.println(name +"->like");
            }
        };
        like4.like("d");
        //4、lambda表达式
        ILike like5 = (name)->{
            System.out.println(name +"->like");
        };
        like5.like("e");
    }


    static class Like2 implements ILike{

        @Override
        public void like(String name) {
            System.out.println(name +"->like");
        }
    }
}
//定义1个函数式接口
interface ILike{
    void like(String name);
}

//实现类
class Like1 implements ILike{

    @Override
    public void like(String name) {
        System.out.println(name +"->like");
    }
}

三、线程状态

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9cPpKRJ3-1616546535001)(多线程.assets/image-20210319112722126.png)]

  • new 新建尚未启动的状态
  • runnable JVM中运行时状态
  • blocked 阻塞状态
  • waiting 正在等待另一个线程执行特定动作
  • timed_waiting 正在等待另一个线程到达指定等待时间
  • terminated 已退出
/**
 * Author:ckvsok
 * Date:2021/3/19
 **/

package thread;
//观察线程状态
public class Demo12 {
    public static void main(String[] args) throws InterruptedException {
        TestStatue testStatue = new TestStatue();
        //
        Thread thread = new Thread(testStatue);
        
        //启动,运行监听
        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(100);
            state = thread.getState();
            System.out.println("状态 :" + state);
        }
    }
}

class TestStatue implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        System.out.println("结束");
    }
}

四、线程方法

  1. setPriority(int newPriority) 设置优先级
  2. static void sleep
  3. void join()
  4. static void yield()
  5. void interrupt
  6. boolean is Alive()

停止线程

  • 不推荐使用JDK提供的stop和destroy方法

  • 推荐线程自己停下来

  • 建议使用一个标志位进行终止变量

    当flag = false,则终止线程运行。

/**
 * Author:ckvsok
 * Date:2021/3/19
 **/

package thread;
//测试线程stop
//1.建议线程正常停止  ---利用次数,不建议死循环
//2.建议使用标志位 --- 设置一个标志位
//3.不要使用stop或者destroy过时的方法
public class Demo10 implements Runnable{

//    1.设置1个标志位
    private boolean flag = true;

    public static void main(String[] args) {
        Demo10 testStopTread = new Demo10();
        new Thread(testStopTread).start();
        for (int i = 0; i < 1000; i++) {
            if (i == 900){
                testStopTread.stop();
                System.out.println("测试线程结束了------------");
            }
            System.out.println("main线程运行 :" + i);
        }
    }

    @Override
    public void run() {
        int i = 0;
        while (flag){
            System.out.println("测试线程运行中:" + i++);
        }
    }
    //2.设置1个公开的方法停止线程,切换标志位
    public void stop(){
        flag = false;
    }
}

线程休眠

  • sleep指定当面线程阻塞的毫秒数
  • sleep存在InterrutedException
  • sleep时间到达后线程进入就绪状态
  • sleep可以模拟网络延时,倒计时等
  • 每个对象都有一个锁,sleep不会释放锁
/**
 * Author:ckvsok
 * Date:2021/3/19
 **/

package thread;

import java.text.SimpleDateFormat;
import java.util.Date;
//模拟倒计时
public class Demo11{
    public static void main(String[] args) {

        countDown();

    }

    public static void countDown(){

        int i = 10;
        while (i>=0){
            try {
                Thread.sleep(1000);
                Date startDate = new Date(System.currentTimeMillis());//获取当前系统时间
                System.out.println("倒计时:" + i -- +" 当前时间:"+ new SimpleDateFormat("HH:mm:ss").format(startDate) );
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

线程礼让

  • 礼让线程,让当前正在执行的线程暂停,但不阻塞
  • 将线程从运行状态转化为就绪状态
  • 让CPU重新调度,礼让不一定成功!看CPU心情

线程join

  • 插队,强制执行
  • 待次线程执行完成后,再执行其他线程,其他线程进入阻塞状态

线程优先级

  • 线程优先级 1- 10
  • 优先级设置建议在start方法前
  • 优先级只是获得调度的概率低
  • setPriority(int newPriority)

守护线程deamon

  • 线程分为用户线程和守护线程
  • 虚拟机必须确保用户线程执行完毕
  • 虚拟机不用等待守护线程执行完毕
  • 守护线程:日志 ,GC等
  • setDaemon();默认是false

五、线程同步(重点)

多个线程操作同一个资源,使用队列和锁解决线程完全问题。

例子1:不安全的买票

/**
 * Author:ckvsok
 * Date:2021/3/19
 **/

package thread;

public class UnsafeBuyTicket {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        new Thread(ticket,"A").start();
        new Thread(ticket,"B").start();
        new Thread(ticket,"C").start();
    }
}

class Ticket implements Runnable{
    private int ticketNub = 10;
    private boolean flag = true; //外部停止条件
    //买票
    @Override
    public void run() {
        while (flag){
            try {
                buy();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void buy() throws InterruptedException {
        //判断是否有票
        if (ticketNub <= 0){
            flag = false;
            return;
        }
        //模拟延时
        Thread.sleep(100);
        //买到了就减一张
        System.out.println(Thread.currentThread().getName() + "买到" + ticketNub --);
    }

}

例子2:银行取钱

/**
 * Author:ckvsok
 * Date:2021/3/19
 **/

package thread;

// 两人从同一个银行账户取钱
public class UnsafeBank {
    public static void main(String[] args) throws InterruptedException {
        Account account = new Account(1000);
        Thread a = new Thread(account, "A");
        Thread b = new Thread(account, "B");

        a.start();
        b.start();
    }
}

//银行账户
class Account implements Runnable {

    //账户金额
    private int money = 100000;
    //账户需要减少的
    private int num;

    public Account(int num){
        this.num = num;
    }

    @Override

    public void run() {
        //取钱
        try {
            takeMoney(num);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void takeMoney(int num) throws InterruptedException {
        while (this.money>num){
            this.money = this.money - num;
            System.out.println(Thread.currentThread().getName()+"取钱"+num+",账户还剩:"+(money));
        }
    }
}

例子3:不安全的买票

/**
 * Author:ckvsok
 * Date:2021/3/19
 **/

package thread;

import java.util.ArrayList;

//ArrayList集合是不安全的, 多线程同时操作一个集合时,会重复操作造成覆盖。
public class UnsafeList {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                list.add(Thread.currentThread().getName());
            }).start();
        }
        System.out.println("list集合含有:" + list.size()+"元素");
    }
}

synchronized

同步方法:synchronized

同步块:synchronized(Object){}

以上都是锁当前对象(this)

死锁现象

多个线程都持有对象的资源,形成僵持。

/**
 * Author:ckvsok
 * Date:2021/3/19
 **/

package thread;

public class TestDeadLock {
    public static void main(String[] args) {
        Makeup girl1 = new Makeup(0, "女朋友1号");
        Makeup girl2 = new Makeup(1, "女朋友2号");
        girl1.start();
        girl2.start();
    }
}

class Makeup extends Thread{
    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);
                //1s后,需要获得镜子的锁
                synchronized (mirror){
                    System.out.println(this.girlName+"获得镜子的锁");
                }
            }
        }else if (choice == 1){
            synchronized(mirror){
                System.out.println(this.girlName+"获得镜子的锁");
                Thread.sleep(1000);
                synchronized (lipstick){
                    System.out.println(this.girlName+"获得口红的锁");
                }
            }
        }
    }
}


//口红
class Lipstick{

}
//镜子
class Mirror{

}

解除死锁,可以一件一件的去做,不要嵌套锁

Lock锁

JDK5.0开始,Lock对象。java.util.concurrent.locks.Lock

ReentrantLock类

实现了Lock,可重入锁。

/**
 * Author:ckvsok
 * Date:2021/3/22
 **/

package thread;

import java.util.concurrent.locks.ReentrantLock;

//测试Lock锁
public class TestLock implements Runnable {

    public static void main(String[] args) {
        TestLock testLock = new TestLock();
        new Thread(testLock).start();
        new Thread(testLock).start();
        new Thread(testLock).start();
    }


    int ticketNum = 10;
    private final ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        try {
            //加锁
            lock.lock();
            while (true) {
                if (ticketNum > 0) {
                    Thread.sleep(1000);
                    System.out.println(ticketNum--);
                } else {
                    break;
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //解锁
            lock.unlock();
        }

    }
}

Lock是显式锁

Lock只有代码锁,相比synchronize性能更好点

六、线程协作

生产者消费者

wait() : 表示线程一直等待,直到其他线程通知,与sleep不同,会释放锁;

notify():唤醒1个处于等待状态的线程;

notifyAll():

以上方法必须在同步代码块中使用,否则有异常。

实现的2种方法:

生产者 --> 缓冲区 —> 消费者

/**
 * Author:ckvsok
 * Date:2021/3/22
 **/

package thread;

//测试:生产者消费者模型 利用缓冲区解决
public class TestPC {
    public static void main(String[] args) {
        SynContainer synContainer = new SynContainer();
        Consumer consumer = new Consumer(synContainer);
        Productor productor = new Productor(synContainer);
        productor.start();
        consumer.start();

    }
}

//消费者
class Consumer extends Thread {
    private SynContainer container;

    public Consumer(SynContainer container) {
        this.container = container;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            Chicken chicken = container.pop();
            System.out.println("消费----产品id: " + chicken.id);
        }
    }
}

//生产者
class Productor extends Thread {
    private 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("生产----产品id:" + i);
        }
    }

}

//缓存区
class SynContainer{
    private static Chicken[] chickens = new Chicken[10];
    private static int count = 0;

    public Chicken[] getChickens() {
        return chickens;
    }

    public void setChickens(Chicken[] chickens) {
        this.chickens = chickens;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    //生产者生产产品
    public synchronized void push(Chicken chicken) {
        //如果容器满了,就等待消费者消费
        if (count == 10) {
            //通知消费者消费,生产者等待
            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;
        //通知生产者生产产品
    }
}
    //产品
    class Chicken {
        int id;

        public Chicken(int id) {
            this.id = id;
        }
    }

信号灯模式:

/**
 * Author:ckvsok
 * Date:2021/3/23
 **/

package thread;

//测试:生产者消费者模型2 信号灯法
public class TestPC2 {
    public static void main(String[] args) {
        Chicken2 chicken2 = new Chicken2();
        Consumer2 consumer = new Consumer2(chicken2);
        Productor2 productor = new Productor2(chicken2);
        productor.start();
        consumer.start();
    }
}

//消费者
class Consumer2 extends Thread {
    private Chicken2 chicken;

    public Consumer2(Chicken2 chicken) {
        this.chicken = chicken;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            try {
                chicken.pop();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

//生产者
class Productor2 extends Thread {
    private Chicken2 chicken;

    public Productor2(Chicken2 chicken) {
        this.chicken = chicken;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            try {
                chicken.push();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

//产品
class Chicken2 {
    boolean flag = true;

    public Chicken2() {
    }

    //生产
    public synchronized void push() throws InterruptedException {
        if (!flag) {
            this.wait();
        }
        flag = !flag;
        System.out.println("正在生产,请等待");
        Thread.sleep(1000);
        this.notifyAll();
    }

    public synchronized void pop() throws InterruptedException {
        if (flag) {
            this.wait();
        }
        flag = !flag;
        System.out.println("正在消费,请等待");
        Thread.sleep(1000);
        this.notifyAll();
    }
}

线程池

提高响应速度,降低资源消耗,

便于线程管理

​ corePoolSize:核心池的大小

​ maxinumPoolSize:最大线程数

​ keepAliveTime 线程没有任务时最多保持多长时间后会终止

ExecutorService :线程池接口

​ void execute(Runnable command)

​ Future submit(Callable task)

​ void shutdown()

Executors : 工具类、线程池的工厂类

高级主题

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值