多线程学习

一、简介

  1. 程序是指令和数据的有序集合,是一个静态概念
  2. 进程是执行程序的一次执行过程,是一个动态概念
  3. 通常在一个进程中可以包含若干个线程
//主线程
public static void main(String[] args) {
        
    }

二、创建线程

  1. 方法一:继承Thread类,重写run()方法,调用start开启线程(注意:线程开启后不一定立即执行,由CPU调度执行)
public class ThreadDemo01 extends Thread{
    //重写run()方法
    public void run(){
        //run方法线程体
        for (int i = 0; i < 10; i++) {
            System.out.println("run"+i);
        }
    }

    //main线程,主线程
    public static void main(String[] args) {
        //创建一个线程对象
        ThreadDemo01 threadDemo01 = new ThreadDemo01();
        //调用start方法开启线程
        threadDemo01.start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("main"+i);
        }
    }

}
  1. 方法二:实现runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法(优点:避免单继承的局限性,方便同一个对象被多个线程使用)
public class ThreadDemo03 implements Runnable{
    //run方法线程体
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("run"+i);
        }
    }

    public static void main(String[] args) {
        //创建runnable接口的实现类对象
        ThreadDemo03 threatDemo03 = new ThreadDemo03();

        //创建线程对象,通过线程对象来开启我们的线程 (代理)
        Thread thread = new Thread(threatDemo03);
        thread.start();
        //new Thread(threatDemo03).start();

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

}

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

//多个线程同时操作同一个对象
//抢票
public class ThreadDemo04 implements Runnable{

    private int ticketNums=10;

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

    public static void main(String[] args) {
        ThreadDemo04 threadDemo04 = new ThreadDemo04();

        new Thread(threadDemo04,"小明").start();
        new Thread(threadDemo04,"小红").start();
        new Thread(threadDemo04,"黄牛").start();
    }
}
  1. 方法三:实现Callable接口(需要返回值);重写call方法(需要抛出异常);创建目标对象;创建执行服务(ExecutorService ser = Executors.newFixedThreadPool(1););提交执行(Future< Boolean > result1 = ser.submit(t1););获取结果(boolean r1 = result1.get(););关闭服务(ser.shutdownNow();)
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.net.URL;
import java.util.concurrent.*;

//练习:用多线程下载图片
public class CallableDemo01 implements Callable<Boolean> {
    private String url;
    private String name;

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

    //线程体
    @Override
    public Boolean call() {
        WebDownloader webDownloader = new WebDownloader();
        webDownloader.down(url,name);
        System.out.println("下载"+name);
        return true;
    }

    public static void main(String[] args) {
        CallableDemo01 t1 = new CallableDemo01("https://cn.bing.com/images/search?view=detailV2&ccid=8olSEek1&id=337FFE50570CBEA0E113BEC16941B5C9B32B8412&thid=OIP.8olSEek1RZjSQDgPizhxEAHaJ3&mediaurl=https%3A%2F%2Fscpic.chinaz.net%2Ffiles%2Fpic%2Fpic9%2F202009%2Fapic27858.jpg&exph=866&expw=650&q=%e5%9b%be%e7%89%87&simid=607999977435913615&form=IRPRST&ck=2ECCC8716D95A1EC8BFBBF273B74945F&selectedindex=0&ajaxhist=0&ajaxserp=0&vt=0&sim=11","e:/1.jpg");
        CallableDemo01 t2 = new CallableDemo01("https://cn.bing.com/images/search?view=detailV2&ccid=nRlAFygd&id=1C8280D2D75B8653FE4F87817387F57189B5AA41&thid=OIP.nRlAFygdctTCHmIWN7GxRwHaEK&mediaurl=https%3A%2F%2Fwww.keaidian.com%2Fuploads%2Fallimg%2F190424%2F24110307_8.jpg&exph=1080&expw=1920&q=%e5%9b%be%e7%89%87&simid=608051753279948997&form=IRPRST&ck=96BDBB01D66DFC3247792098BAA2CA28&selectedindex=1&ajaxhist=0&ajaxserp=0&vt=0&sim=11","e:/2.jpg");
        CallableDemo01 t3 = new CallableDemo01("https://cn.bing.com/images/search?view=detailV2&ccid=xSB%2F5yZF&id=3AD3C13EEA5DE64CBD1E2D690FEA5DFB10106011&thid=OIP-C.xSB_5yZFzr3OR8HJ6IiAzAHaEq&mediaurl=https%3A%2F%2Fts1.cn.mm.bing.net%2Fth%2Fid%2FR-C.c5207fe72645cebdce47c1c9e88880cc%3Frik%3DEWAQEPtd6g9pLQ%26riu%3Dhttp%253a%252f%252fimg95.699pic.com%252fphoto%252f50077%252f2014.jpg_wh860.jpg%26ehk%3DF6l1C0wu%252bIt8eAzaHiQOvG7EAFjtMKGbgHMLAbi8XP4%253d%26risl%3D%26pid%3DImgRaw%26r%3D0&exph=541&expw=860&q=%e5%9b%be%e7%89%87&simid=608034745203441249&form=IRPRST&ck=12C66ABF14C2933DE1D50A05D744BE59&selectedindex=2&ajaxhist=0&ajaxserp=0&vt=0&sim=11","e:/3.jpg");
        //创建执行服务
        ExecutorService ser = Executors.newFixedThreadPool(3);

        //提交执行
        Future<Boolean> r1 = ser.submit(t1);
        Future<Boolean> r2 = ser.submit(t2);
        Future<Boolean> r3 = ser.submit(t3);

        //获取结果(抛出异常)
        try {
            boolean rst1=r1.get();
            boolean rst2=r2.get();
            boolean rst3=r3.get();
            System.out.println(rst1);
            System.out.println(rst2);
            System.out.println(rst3);
        }catch (Exception e){
            e.printStackTrace();
        }

        //关闭服务
        ser.shutdownNow();

    }

}


//下载器
class WebDownloader{
    //下载方法
    public void down(String url,String name) {
        try {
            FileUtils.copyURLToFile(new URL(url),new File(name));
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

三、静态代理对象

//静态代理
//真实对象和代理对象都要实现同一个接口;代理对象要代理真实的角色
//代理的好处:代理对象可以做很多真实对象做不了的事;真实对象可以专心做自己的事
public class StaticProxy {
    public static void main(String[] args) {
        You you = new You();
        WeddingCompany weddingCompany = new WeddingCompany(you);
        weddingCompany.HappyMarry();
    }
}

//定义接口
interface Marry{
    public void HappyMarry();
}

//真实对象类
class You implements Marry{
    @Override
    public void HappyMarry() {
        System.out.println("你要结婚了");
    }
}

//代理对象类
class WeddingCompany implements Marry{
    public Marry target;//需要被代理的目标对象

    public WeddingCompany(Marry target) {
        this.target = target;//真实对象
    }

    @Override
    public void HappyMarry() {
        before();
        this.target.HappyMarry();
        after();
    }

    public void before(){
        System.out.println("婚前布局");
    }
    public void after(){
        System.out.println("婚后结尾款");
    }
}

四、Lamda表达式

  1. 函数式接口:任何接口如果只包含唯一一个抽象方法,那么它就是一个函数式接口
例如:
public interface Runnable{
	public abstract void run();
}
  1. 对于函数式接口,可以通过Lambda表达式来创建该接口的对象
public class Demo01 {
    //3.静态内部类
    static class Like2 implements ILike{
        @Override
        public void Lambda() {
            System.out.println("i like lambda2");
        }
    }


    public static void main(String[] args) {
        //实现类的调用方法
        ILike like = new Like();//创建接口对象
        like.Lambda();

        //静态内部类的调用方法
        ILike like2 = new Like2();
        like2.Lambda();

        //4.局部内部类
        class Like3 implements ILike{
            @Override
            public void Lambda() {
                System.out.println("i like lambda3");
            }
        }

        //局部内部类的调用方法
        ILike like3 = new Like3();
        like3.Lambda();

        //5.匿名内部类,没有类的名称,必须借助接口或父类
        ILike like4 = new ILike() {
            @Override
            public void Lambda() {
                System.out.println("i like lambda4");
            }
        };

        //匿名内部类的调用方法
        like4.Lambda();

        //6.用Lambda简化
        ILike like5 = ()->{
            System.out.println("i like lambda5");
        };
        like5.Lambda();
    }
}

//1.定义一个函数接口
interface ILike{
    void Lambda();
}

//2.实现类
class Like implements ILike{
    @Override
    public void Lambda() {
        System.out.println("i like lambda");
    }
}

五、线程停止

  1. 建议线程正常停止(利用次数,不建议死循环)
  2. 建议使用标志位(设置一个标志位)
  3. 不要使用stop或destroy等方法,自己建方法
public class Demo01 implements Runnable{
    //设置标识位
    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) {
        Demo01 demo01 = new Demo01();

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

        for (int i = 0; i < 1000; i++) {
            System.out.println("main"+i);
            if (i==900){
                //调用stop方法转换标志位,让线程停下来
                demo01.stop();
                System.out.println("线程停止了");
            }
        }
    }
}


六、线程休眠

  1. sleep(时间) 指当前线程阻塞的毫秒数
  2. sleep存在异常InterruptedException,需要抛出
  3. sleep时间达到后线程进入就绪状体
  4. sleep可以模拟网络延时、倒计时等
  5. 每个对象都有一个锁,sleep不会释放锁
//模拟网络延迟:可以放大问题的发生性
public class Demo01 implements Runnable{
    private int ticket = 10;

    @Override
    public void run() {
        while (true) {
            if (ticket<0){
                break;
            }
            try {
                Thread.sleep(10);

            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "拿到了第" + ticket-- + "张票");
        }
    }

    public static void main(String[] args) {
        Demo01 demo01 = new Demo01();
        new Thread(demo01,"小明").start();
        new Thread(demo01,"老师").start();
        new Thread(demo01,"黄牛").start();
    }
}
public class Demo02 {
    public static void main(String[] args) {
        numDown();
        timeDown();
    }

    //倒计时
    public static void numDown(){
        int num = 10;
        while (true){
            try {
                Thread.sleep(1000);
                System.out.println(num--);
            }catch (Exception e){
                e.printStackTrace();
            }
            if (num<0){
                break;
            }
        }
    }

    //获取时间
    public static void timeDown(){
        //打印当前系统时间
        Date startTime = new Date(System.currentTimeMillis());//获取当前系统时间
        while (true){
            try {
                Thread.sleep(1000);
                System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
                startTime = new Date(System.currentTimeMillis());//更新当前时间
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

七、线程礼让

  1. 让当前正在执行的线程暂停,但不阻塞
  2. 将线程从运行状态转为就绪状态,让cpu重新调度
  3. 礼让不一定成功
public class Demo01 {
    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()+"线程结束");
    }
}

八、线程强制执行

  1. Join 合并线程,待此线程执行完成后,在执行其他线程(类似于插队)
  2. 需要抛出异常
public class Demo01 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("线程vip来了"+i);
        }

    }

    public static void main(String[] args) {
        Demo01 demo01 = new Demo01();
        Thread thread = new Thread(demo01);
        thread.start();

        for (int i = 0; i < 500; i++) {
            if (i==200){
                try {
                    new Thread(demo01).join();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            System.out.println("主线程"+i);
        }
    }
}

九、观察线程状态

public class Demo01 {
    public static void main(String[] args) {
        Thread thread = new Thread(()->{
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            System.out.println("//");
        });

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

        //观察启动状态
        thread.start();
        state = thread.getState();
        System.out.println(state);

        while (state!=Thread.State.TERMINATED){//只要线程不终止,就会一直循环
            try {
                Thread.sleep(100);
            }catch (Exception e){
                e.printStackTrace();
            }
            state = thread.getState();
            System.out.println(state);
        }
    }
}

十、线程优先级

使用getPriority()和setPriorty()进行获取和设置
一般情况下优先级高的先执行

public class Demo01 {
    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);
        Thread t5 = new Thread(myPriority);

        t1.start();//优先级默认是5

        t2.setPriority(1);
        t2.start();

        t3.setPriority(8);
        t3.start();

        t4.setPriority(Thread.MAX_PRIORITY);//这里是优先级的最大值,即 MAX_PRIORITY=10
        t4.start();

        t5.setPriority(7);
        t5.start();
    }
}

class MyPriority implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"----->"+Thread.currentThread().getPriority());
    }
}

十一、守护线程

  1. 线程分为用户线程和守护线程
  2. 虚拟机必须确保用户线程执行完毕,不用等待守护线程执行完毕
public class Demo01 {
    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("Hello "+i);
        }
        System.out.println("===============goodbye=============");
    }
}

十二、线程同步(队列 加 锁)

  1. 同步方法(在方法中加入synchronized变为同步方法,默认对象是该方法)
public class Demo01 {
    public static void main(String[] args) {
        GrabTicket grabTicket = new GrabTicket();

        new Thread(grabTicket,"小明").start();
        new Thread(grabTicket,"老师").start();
        new Thread(grabTicket,"黄牛").start();

    }
}

class GrabTicket implements Runnable{
    private int ticket = 10;
    boolean flag = true;

    @Override
    public void run() {
        while (flag){
            buy();
        }
    }

    //synchronized 同步方法,默认锁的是this
    public synchronized void buy(){
        if (ticket<=0){
            flag = false;
            return;
        }
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"拿到了第"+ticket--+"张票");
    }
}
  1. 同步块(synchronized(Obj){…},obj为同步监听器,默认为this,锁的对象是会发生变化的对象)
public class Demo02 {
    public static void main(String[] args) {
        Account account = new Account("总",1000);

        Bank zhang= new Bank(account,500,"zhang");
        Bank wang = new Bank(account,1000,"wang");

        zhang.start();
        wang.start();
    }
}

//账户
class Account{
    String name;
    int money;
    public Account(String name , int money){
        this.name = name;
        this.money = money;
    }
}

//银行取钱
class Bank extends Thread{
    Account account;
    int drawingMoney;//取多少钱
    int nowMoney;//剩多少钱
    String name;

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

    @Override
    public void run() {
        //锁的对象是变化的量,增删改
        synchronized (account){
            if (drawingMoney > account.money){
                System.out.println(account.name+"钱不够");
                return;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            account.money = account.money-drawingMoney;
            nowMoney = nowMoney+drawingMoney;
            System.out.println(name+"余额为:"+account.money);
            System.out.println(name+"手里的钱:"+nowMoney);

        }

    }
}

十三、CopyOnWriteArrayList

//测试JUC安全类型的集合
public class Demo03 {
    public static void main(String[] args) {
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                list.add(Thread.currentThread().getName());
            }).start();
        }
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

十四、死锁

  1. 产生条件:
    (1)互斥条件:一个资源每次只能被一个进程使用
    (2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放
    (3)不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺
    (4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
//这样就会形成死锁
if (choice==1){
            synchronized (gan){
                System.out.println(this.name+"获得了枪");
                sleep(100);
                synchronized (car){
                    System.out.println(this.name+"获得了车");
                }
            }
        }else {
            synchronized (car){
                System.out.println(this.name+"获得了车");
                sleep(100);
                synchronized (gan){
                    System.out.println(this.name+"获得了枪");
                }
            }
        }

处理死锁:

public class Demo01 {
    public static void main(String[] args) {
        Play p1 = new Play(1,"zhang");
        Play p2 = new Play(0,"lin");
        p1.start();
        p2.start();
    }
}

//枪
class Gan{

}

//车
class Car{

}

class Play extends Thread{
    static Gan gan = new Gan();
    static Car car = new Car();

    int choice;
    String name ;

    public Play(int choice,String name){
        this.choice = choice;
        this.name = name;
    }

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

    public void play() throws InterruptedException {
        if (choice==1){
            synchronized (gan){
                System.out.println(this.name+"获得了枪");
                sleep(100);
            }
            synchronized (car){
                System.out.println(this.name+"获得了车");
            }
        }else {
            synchronized (car){
                System.out.println(this.name+"获得了车");
                sleep(100);
                }
            synchronized (gan){
                System.out.println(this.name+"获得了枪");
            }
        }
    }
}

十五、Lock锁

public class Demo01 {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        new Thread(ticket).start();
        new Thread(ticket).start();
        new Thread(ticket).start();
    }
}

class Ticket implements Runnable{
    int ticket = 10;
    private final ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        try {
            lock.lock();
            while (true){
                if (ticket<=0){
                    break;
                }
                System.out.println(ticket--);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }finally {
            lock.unlock();
        }


    }
}

Lock 与 synchronized 的对比:

  1. Lock是显示锁(手动开启和关闭锁),synchronized 是隐式锁(出来作用域自动关闭)
  2. Lock只有代码块锁 ,synchronized 有代码块锁和方法锁
  3. Lock锁JVM花费较少时间来调度(性能好,并且具有更好的扩展性)

十六、线程通信

wait(); //表示线程一直等待,直到其他线程通知,与sleep不同,会释放锁
wait(long timeout); //指定等待的毫秒数
notify(); //唤醒一个处于等待转态的线程
notifyAll(); //唤醒同一个对象上所有调用wait()方法的线程,优先级别高的线程优先调度
  1. 管程法
//测试:生产者消费者模型--->利用缓冲区解决管程法

//生产者、消费者、缓冲区、产品

public class Test {
    public static void main(String[] args) {
        Buffer buffer = new Buffer();
        new Producer(buffer).start();
        new Consumer(buffer).start();
    }
}

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

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            buffer.push(new Chicken(i));
            System.out.println("生产了"+i+"只鸡");
        }

    }
}

//消费者
class Consumer extends Thread{
    Buffer buffer;
    public Consumer(Buffer buffer){
        this.buffer = buffer;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("消费了----->"+buffer.pop().id+"只鸡");
        }
    }
}

//产品
class Chicken{
    int id ;//编号

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

//缓冲区
class Buffer{
    //需要容器的大小
    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;
    }

}
  1. 信号灯法
//测试生产者消费者模式2:信号灯方法,标志位解决
public class Test2 {
    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 {
                System.out.println("广告");
            }
        }
    }
}

//消费者--->观众
class Watcher extends Thread{
    TV tv;
    public Watcher(TV tv){
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            this.tv.watch();
        }
    }
}

//产品--->节目
class TV{
    //演员表演,观众等待  --- T
    //观众观看,演员等待  --- F
    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;
    }
}

十七、线程池

  1. 经常船创建和销毁、使用量大的资源,比如并发情况下的线程,对性能影响很大
  2. 提前创建好多个线程,放到线程池中,使用时直接获取,使用完放回池中
  3. 提高了响应速度(减少了创建新线程的时间);降低资源消耗(重复利用线程池中线程,不需要每次都创建);便于线程管理
public class Demo01 {
    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());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值