Java面向对象-多线程

目录

 一.多线程的创建

        1.方式一:继承Thread类

        2.方式二:实现Runnable接口

        3.方式三:JDK 5.0新增:实现Callable接口

二.Thread的常用方法

三.线程安全

1.线程安全问题是什么,发生的原因

2.线程安全模拟

四.线程同步

1.同步思想概述

2.方法一:同步代码块

3.方法二:同步方法

3.Lock锁

五.线程通信

六.线程池(重点:面试必问)

1.线程池概述

2.线程池实现API,参数说明

3.线程池处理Runnable任务

4.线程处理Callable任务

5.Excutors工具类实现线程池

七.补充知识:定时器

八.补充知识:并发、并行

九.补充知识:线程的生命周期


 一.多线程的创建

        1.方式一:继承Thread类

 

package com.wjh.d1_create;
/*
    目标:多线程的创建方式之一:继承Thread类实现
 */

public class ThreadDemo1 {
    public static void main(String[] args) {
        //3.new一个新线程对象
        Thread t = new MyThread();
        //4.调用start方法启动线程(执行的还是run方法)
        t.start();

        for (int i = 0; i < 5; i++) {
            System.out.println("主线程执行输出:" + i);
        }


    }
}

/*
    1.定义一个线程类继承Thread类
 */
class MyThread extends Thread{

    /*
        2.重写run方法,里面是定义线程以后要做的事情
     */
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("子线程执行输出:" + i);
        }
    }
}

子线程执行输出:0
主线程执行输出:0
主线程执行输出:1
主线程执行输出:2
主线程执行输出:3
主线程执行输出:4
子线程执行输出:1
子线程执行输出:2
子线程执行输出:3
子线程执行输出:4

进程已结束,退出代码为 0

        2.方式二:实现Runnable接口

 

package com.wjh.d1_create;
/*
    目标:学会线程的创建方式二:理解他的优缺点.
 */

public class ThreadDemo2 {
    public static void main(String[] args) {
        //3.创建一个任务对象
        Runnable runnable = new MyRunnable();

        //4.把任务对象交给Thread处理
        Thread t =new Thread(runnable);

        //5.启动线程
        t.start();

        //主线程任务:
        for (int i = 0; i < 10; i++) {
            System.out.println("主线程执行输出:" + i);
        }
        
    }
}

/*
    定义一个线程任务类 实现Runnable接口
 */
class MyRunnable extends Object implements Runnable{
    /*
        2.重写run方法,定义线程的执行任务
     */

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("子线程执行输出:" + i);
        }
    }
}

主线程执行输出:0
主线程执行输出:1
子线程执行输出:0
主线程执行输出:2
子线程执行输出:1
主线程执行输出:3
子线程执行输出:2
主线程执行输出:4
子线程执行输出:3
主线程执行输出:5
主线程执行输出:6
子线程执行输出:4
主线程执行输出:7
子线程执行输出:5
子线程执行输出:6
子线程执行输出:7
子线程执行输出:8
主线程执行输出:8
子线程执行输出:9
主线程执行输出:9

进程已结束,退出代码为 0

 

 

package com.wjh.d1_create;
/*
    目标:学会线程的创建方式二:(匿名内部类方法实现,语句形式)
 */

public class ThreadDemo2_Other {
    public static void main(String[] args) {
        //3.创建一个任务对象(匿名内部类)
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                     System.out.println("子线程1执行输出:" + i);
                }
            }
        };

        //4.把任务对象交给Thread处理
        Thread t =new Thread(runnable);

        //5.启动线程
        t.start();

        //简化写法1
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                     System.out.println("子线程2执行输出:" + i);

                }
            }
        }).start();

        //简化写法2
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.println("子线程3执行输出:" + i);

            }
        }).start();



        //主线程任务:
        for (int i = 0; i < 10; i++) {
            System.out.println("主线程执行输出:" + i);
        }

    }
}

子线程3执行输出:0
主线程执行输出:0
子线程2执行输出:0
子线程2执行输出:1
子线程1执行输出:0
子线程2执行输出:2
子线程1执行输出:1
主线程执行输出:1
子线程3执行输出:1
主线程执行输出:2
主线程执行输出:3
子线程1执行输出:2
子线程1执行输出:3
子线程1执行输出:4
子线程2执行输出:3
子线程1执行输出:5
子线程2执行输出:4
子线程2执行输出:5
主线程执行输出:4
主线程执行输出:5
主线程执行输出:6
主线程执行输出:7
主线程执行输出:8
主线程执行输出:9
子线程3执行输出:2
子线程2执行输出:6
子线程1执行输出:6
子线程1执行输出:7
子线程1执行输出:8
子线程1执行输出:9
子线程2执行输出:7
子线程2执行输出:8
子线程2执行输出:9
子线程3执行输出:3
子线程3执行输出:4
子线程3执行输出:5
子线程3执行输出:6
子线程3执行输出:7
子线程3执行输出:8
子线程3执行输出:9

进程已结束,退出代码为 0
 

        3.方式三:JDK 5.0新增:实现Callable接口

 

 

package com.wjh.d1_create;
/*
    目标:多线程的创建方式之三:实现Callable接口,结合FutureTask完成.

 */

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class ThreadDemo3 {
    public static void main(String[] args) {
        //3.创建Callable任务对象
        Callable<String> call1 = new MyCallable(100);    //传参

        //4.把callable任务对象交给FutureTask对象
        //FutureTask对象的作用1:是Runnable对象(实现了Runnable接口),可以交给Thread了
        //FutureTask对象的作用2:可以在线程执行完毕之后调用其get方法得到线程执行完成的结果
        FutureTask<String> f1 = new FutureTask<>(call1);

        //5.交给线程处理
        Thread t1 = new Thread(f1);

        //6.启动线程
        t1.start();

        //=====================================================================

        //3.创建Callable任务对象
        Callable<String> call2 = new MyCallable(200);    //传参

        //4.把callable任务对象交给FutureTask对象
        //FutureTask对象的作用1:是Runnable对象(实现了Runnable接口),可以交给Thread了
        //FutureTask对象的作用2:可以在线程执行完毕之后调用其get方法得到线程执行完成的结果
        FutureTask<String> f2 = new FutureTask<>(call2);

        //5.交给线程处理
        Thread t2 = new Thread(f2);

        //6.启动线程
        t2.start();

        //=====================================================================

        try {
            //如果f1没有执行完毕!,这里的代码会等待,知道线程1跑完才提取结果.
            String rs1 = f1.get();
            System.out.println("第一个结果:" + rs1);
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            String rs2 = f2.get();
            System.out.println("第二个结果:" + rs2);
        } catch (Exception e) {
            e.printStackTrace();
        }



    }

}

/*
    定义一个任务类,实现Callable接口 必须申明线程任务执行完毕后的结果的数据类型
 */
class MyCallable implements Callable<String>{   //<String> -> 返回
    private int n;

    public MyCallable(int n) {
        this.n = n;
    }



    /*
        重写call方法(线程的任务方法)
     */

    @Override
    public String call() throws Exception {
        int count = 0;
        for (int i = 1; i <= n; i++) {
            count += i;
        }
        return "子线程执行的结果是:" + count;
    }
}

第一个结果:子线程执行的结果是:5050
第二个结果:子线程执行的结果是:20100

进程已结束,退出代码为 0

二.Thread的常用方法

package com.wjh.d2_api;

public class MyThread extends Thread{
    public MyThread() {

    }

    public MyThread(String name) {
        //为当前对象设置名称
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + "线程输出:" + i);
            //默认名字 Thread-1 / Thread-0
        }
    }
}
package com.wjh.d2_api;

public class ThreadDemo1 {
    public static void main(String[] args) {
        Thread t1 = new MyThread("1号");
        //t1.setName("1号");
        t1.start();
        System.out.println(t1.getName());

        Thread t2 = new MyThread("2号");
        //t2.setName("2号");
        t2.start();
        System.out.println(t2.getName());


        //哪个线程执行它,它就得到哪个线程对象(当前线程对象)
        //主线程的名称就叫main
        Thread m = Thread.currentThread();
        System.out.println(m.getName());
        m.setName("最牛");

        for (int i = 0; i < 5; i++) {
            System.out.println(m.getName() + "线程输出:" + i);
        }

    }
}

1号
2号
main
最牛线程输出:0
最牛线程输出:1
最牛线程输出:2
最牛线程输出:3
最牛线程输出:4
1号线程输出:0
1号线程输出:1
1号线程输出:2
1号线程输出:3
1号线程输出:4
2号线程输出:0
2号线程输出:1
2号线程输出:2
2号线程输出:3
2号线程输出:4

进程已结束,退出代码为 0

package com.wjh.d2_api;
/*
    目标:线程的API
 */

public class ThreadDemo2 {
    //main方法就是由主线程负责调度的
    public static void main(String[] args) throws Exception{
        for (int i = 1; i <= 5 ; i++) {
            System.out.println("输出:" + i);
            if(i == 3){
                //让线程进入休眠状态
                //段子:项目经理让加,如果愿意交钱,就注释掉
                Thread.sleep(3000); //单位毫秒
            }
        }

    }
}

输出:1
输出:2
输出:3
输出:4
输出:5

进程已结束,退出代码为 0

//4.把任务对象交给Thread处理
        Thread t =new Thread(runnable, "1号");

三.线程安全

1.线程安全问题是什么,发生的原因

2.线程安全模拟

账户类:

package com.wjh.d3_thread_saft;
//账户类
public class Account {
    private String cardId;
    private double money;

    public Account() {

    }

    public Account(String cardId, double money) {
        this.cardId = cardId;
        this.money = money;
    }

    /**
     * 小明 小红
     * @param money
     */
    public void drawMoney(double money) {
        //先获取是谁来取钱
        String name = Thread.currentThread().getName();
        //1.判断账户余额是否足够
        if (this.money >= money){
            //2.取钱
            System.out.println(name + "来取钱,取走:" + money);
            //3.更新余额
            this.money -= money;
            System.out.println(name + "来取钱,剩余余额:" + this.money);

        }else{
            System.out.println(name + "来取钱,余额不足!");
        }
    }

    public String getCardId() {
        return cardId;
    }

    public void setCardId(String cardId) {
        this.cardId = cardId;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

}

线程类:

package com.wjh.d3_thread_saft;
/*
    取钱的线程类
 */
public class DrawThead extends Thread{
    private Account acc;

    public DrawThead(Account acc,String name) {
        super(name);
        this.acc = acc;
    }

    @Override
    public void run() {
        //  小明/小红:取钱
        acc.drawMoney(100000);

    }
}

测试类:

package com.wjh.d3_thread_saft;
/*
    需求:
        小明和小红是一对夫妻,他们有一个共同的账户,余额是10万元,模拟2人同时去取钱10万。
    分析:
        ①:需要提供一个账户类,创建一个账户对象代表2个人的共享账户。
        ②:需要定义一个线程类,线程类可以处理账户对象。
        ③:创建2个线程对象,传入同一个账户对象。
        ④:启动2个线程,去同一个账户对象中取钱10万。
 */

public class ThreadDemo1 {
    public static void main(String[] args) {
        //1.定义一个账户类对象,创建一个共享账户
        Account acc = new Account("622682",100000);

        //2.开始创建2个线程对象,代表小明和小红同时进来了
        new DrawThead(acc, "小明").start();
        new DrawThead(acc, "小红").start();


    }
}

小红来取钱,取走:100000.0
小明来取钱,取走:100000.0
小红来取钱,剩余余额:0.0
小明来取钱,剩余余额:-100000.0

进程已结束,退出代码为 0
 

(出现了线程安全问题)

四.线程同步

1.同步思想概述

 

 

2.方法一:同步代码块

//同步代码块(小明- 小红) : Ctrl + Alt + t 
        synchronized ("wjh") {
            //1.判断账户余额是否足够
            if (this.money >= money){
                //2.取钱
                System.out.println(name + "来取钱,取走:" + money);
                //3.更新余额
                this.money -= money;
                System.out.println(name + "来取钱,剩余余额:" + this.money);

            }else{
                System.out.println(name + "来取钱,余额不足!");
            }
        }

//    //加入100个线程调用
//    public static void run(){
//        synchronized (Account.class){
//
//        }
//    }

3.方法二:同步方法

    /**
     * 小明 小红
     * @param money
     */
    public synchronized void drawMoney(double money) {
        //先获取是谁来取钱
        String name = Thread.currentThread().getName();

        //同步代码块(小明- 小红) : Ctrl + Alt + t

        //操作同一个账户 (this) == acc
            //1.判断账户余额是否足够
            if (this.money >= money){
                //2.取钱
                System.out.println(name + "来取钱,取走:" + money);
                //3.更新余额
                this.money -= money;
                System.out.println(name + "来取钱,剩余余额:" + this.money);

            }else{
                System.out.println(name + "来取钱,余额不足!");
            }
    }

3.Lock锁


    //加final修饰,唯一不可替换
    private final Lock lock = new ReentrantLock();
    /**
     * 小明 小红
     * @param money
     */
    public  void drawMoney(double money) {
        //先获取是谁来取钱
        String name = Thread.currentThread().getName();

        //同步代码块(小明- 小红) : Ctrl + Alt + t
        lock.lock();    //上锁

        //操作同一个账户 (this) == acc
            //1.判断账户余额是否足够
        try {
            if (this.money >= money){
                //2.取钱
                System.out.println(name + "来取钱,取走:" + money);
                //3.更新余额
                this.money -= money;
                System.out.println(name + "来取钱,剩余余额:" + this.money);
            }else{
                System.out.println(name + "来取钱,余额不足!");
            }
        } finally { //不管程序报不报错,finally都要执行!
            lock.unlock();   //解锁
        }
    }

五.线程通信

 

账户类:

package com.wjh.d7_thread_comunication;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

//账户类
public class Account {
    private String cardId;
    private double money;


    public Account() {

    }

    public Account(String cardId, double money) {
        this.cardId = cardId;
        this.money = money;
    }

    /**
     * 亲爹 岳父 干爹 存钱(注意线程安全)
     * @param money
     */
    public synchronized void depositMoney(double money) {
        try {
            String name = Thread.currentThread().getName();
            if(this.money == 0){
                //没钱
                this.money += money;
                System.out.println(name + "来存钱:" + money +"成功! 余额是:" + this.money);
                //有钱了,唤醒别人,等待自己!
                this.notifyAll();   //唤醒所有线程
                this.wait();    //锁对象,让当前进程进入等待!
            }else{
                //System.out.println(name + "来存钱:没钱");
                //有钱,不可存
                //唤醒别人.等待自己
                this.notifyAll();   //唤醒所有线程
                this.wait();    //锁对象,让当前进程进入等待!
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 小明/小红 取钱(注意线程安全)
     * @param money
     */
    public synchronized void drawMoney(double money) {
        try {
            String name = Thread.currentThread().getName();
            if(this.money >= money){
                //钱够
                this.money -= money;
                System.out.println(name + "来取钱:" + money +"成功! 余额是:" + this.money);
            }else{
                //System.out.println(name + "来取钱:没钱");
                //钱不够,不可取
                //唤醒别人.等待自己
                this.notifyAll();   //唤醒所有线程
                this.wait();    //锁对象,让当前进程进入等待!
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    public String getCardId() {
        return cardId;
    }

    public void setCardId(String cardId) {
        this.cardId = cardId;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

}

存钱线程类:

package com.wjh.d7_thread_comunication;

/*
    存钱的线程类
 */
public class DepositThead extends Thread{
    private Account acc;

    public DepositThead(Account acc, String name) {
        super(name);
        this.acc = acc;
    }
    @Override
    public void run() {
        while (true) {
            //亲爹 岳父 干爹都来存钱
            acc.depositMoney(100000);
            try {
                Thread.sleep(4000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

取钱线程类:

package com.wjh.d7_thread_comunication;

import com.wjh.d7_thread_comunication.Account;

/*
    取钱的线程类
 */
public class DrawThead extends Thread{
    private Account acc;

    public DrawThead(Account acc, String name) {
        super(name);
        this.acc = acc;
    }
    @Override
    public void run() {
        while (true) {
            //小明和小红都来取钱
            acc.drawMoney(100000);
            try {
                Thread.sleep(4000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

测试类:

package com.wjh.d7_thread_comunication;
/*
    目标:了解线程通信的流程
 */

public class ThreadDemo {
    public static void main(String[] args) {
        //使用3个父亲存钱(生产者),2个孩子取钱(消费者) 模拟线程通信思想(一存100000,一取100000)
        //1.创建账户对象,代表5个人共同操作的账户
        Account acc = new Account("622682",0);
        //2.创建两个取钱线程代表小明和小红
        new DrawThead(acc, "小明").start();
        new DrawThead(acc, "小红").start();

        //3.创建三个存钱线程代表:亲爹 岳父 干爹
        new DepositThead(acc, "亲爹").start();
        new DepositThead(acc, "岳父").start();
        new DepositThead(acc, "干爹").start();

    }
}

亲爹来存钱:100000.0成功! 余额是:100000.0
小明来取钱:100000.0成功! 余额是:0.0
亲爹来存钱:100000.0成功! 余额是:100000.0
小明来取钱:100000.0成功! 余额是:0.0
亲爹来存钱:100000.0成功! 余额是:100000.0
小明来取钱:100000.0成功! 余额是:0.0
干爹来存钱:100000.0成功! 余额是:100000.0
小红来取钱:100000.0成功! 余额是:0.0
亲爹来存钱:100000.0成功! 余额是:100000.0
小明来取钱:100000.0成功! 余额是:0.0
岳父来存钱:100000.0成功! 余额是:100000.0
小明来取钱:100000.0成功! 余额是:0.0
亲爹来存钱:100000.0成功! 余额是:100000.0
小明来取钱:100000.0成功! 余额是:0.0
干爹来存钱:100000.0成功! 余额是:100000.0
小明来取钱:100000.0成功! 余额是:0.0
岳父来存钱:100000.0成功! 余额是:100000.0
小红来取钱:100000.0成功! 余额是:0.0
干爹来存钱:100000.0成功! 余额是:100000.0
小明来取钱:100000.0成功! 余额是:0.0
亲爹来存钱:100000.0成功! 余额是:100000.0
小红来取钱:100000.0成功! 余额是:0.0
岳父来存钱:100000.0成功! 余额是:100000.0

进程已结束,退出代码为 -1

六.线程池(重点:面试必问)

1.线程池概述

2.线程池实现API,参数说明

 (重点)

3.线程池处理Runnable任务

package com.wjh.d8_threadpool;

public class MyRunnable implements Runnable {

    private int count = 0;
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            count++;
            System.out.println(count + ":" + Thread.currentThread().getName() + "输出了:HelloWord ==>" + i);
        }
            try {
                System.out.println(Thread.currentThread().getName() + "正在休眠...");
                Thread.sleep(50000000);
            } catch (Exception e) {
                e.printStackTrace();
            }
    }
}
package com.wjh.d8_threadpool;
/*
    目标:自定义一个线程池对象,并测试其特性!
 */

import java.util.concurrent.*;

public class TheadPoolDemo1 {
    public static void main(String[] args) {
        //1.创建线程池对象
        /*
        public ThreadPoolExecutor(int corePoolSize, -> 主线程数量
                              int maximumPoolSize,  -> 最大线程数
                              long keepAliveTime,   -> 临时线程最大存活时间
                              TimeUnit unit,    ->  存活时间的单位
                              BlockingQueue<Runnable> workQueue,    -> 指定任务队列
                              ThreadFactory threadFactory,  -> 指定用哪个线程工厂创建线程
                              RejectedExecutionHandler handler){    -> 处理临时线程(任务拒绝策略)
                                        , 默认:new ThreadPoolExecutor.AbortPolicy() -> (对方正在忙,并向你抛了一个异常)
                              }
         */
        ExecutorService pool = new ThreadPoolExecutor(3, 5, 6, TimeUnit.SECONDS
                , new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

        //2.给任务线程池处理
        Runnable target = new MyRunnable();
        pool.execute(target);   //thread-1
        pool.execute(target);   //thread-2
        pool.execute(target);   //thread-3

        pool.execute(target);   //thread-4
        pool.execute(target);   //thread-5
        pool.execute(target);   //thread-6
        pool.execute(target);   //thread-7
        pool.execute(target);   //thread-8

        //创建临时线程
        pool.execute(target);   //thread-9
        pool.execute(target);   //thread-10

        //开始抛异常(触发拒绝策略)
        //pool.execute(target);   //thread-11

        //关闭线程池(一般不使用)
        //pool.shutdownNow();     //立即关闭,即使任务还没有完成,会丢失任务的!
        //pool.shutdown();     //会等待全部任务执行完毕之后再关闭 (建议使用)


    }
}

4.线程处理Callable任务

package com.wjh.d8_threadpool;
/*
    目标:多线程的创建方式之三:实现Callable接口,结合FutureTask完成.

 */

import java.util.concurrent.Callable;

/*
    定义一个任务类,实现Callable接口 必须申明线程任务执行完毕后的结果的数据类型
 */
public class MyCallable implements Callable<String>{   //<String> -> 返回
    private int n;

    public MyCallable(int n) {
        this.n = n;
    }



    /*
        重写call方法(线程的任务方法)
     */

    @Override
    public String call() throws Exception {
        int count = 0;
        for (int i = 1; i <= n; i++) {
            count += i;
        }
        return Thread.currentThread().getName() + "执行1-" + n + "子线程执行的结果是:" + count;
    }
}
package com.wjh.d8_threadpool;
/*
    目标:自定义一个线程池对象,并测试其特性!
 */

import java.util.concurrent.*;

public class TheadPoolDemo2 {
    public static void main(String[] args) throws Exception{
        //1.创建线程池对象
        /*
        public ThreadPoolExecutor(int corePoolSize, -> 主线程数量
                              int maximumPoolSize,  -> 最大线程数
                              long keepAliveTime,   -> 临时线程最大存活时间
                              TimeUnit unit,    ->  存活时间的单位
                              BlockingQueue<Runnable> workQueue,    -> 指定任务队列
                              ThreadFactory threadFactory,  -> 指定用哪个线程工厂创建线程
                              RejectedExecutionHandler handler)
                              {    -> 处理临时线程(任务拒绝策略)    ->  默认:new ThreadPoolExecutor.AbortPolicy() -> (对方正在忙,并向你抛了一个异常)
                              }
         */
        ExecutorService pool = new ThreadPoolExecutor(3, 5, 6, TimeUnit.SECONDS
                , new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

        //2.给任务线程池处理
        Future<String> f1 = pool.submit(new MyCallable(100));
        Future<String> f2 = pool.submit(new MyCallable(200));
        Future<String> f3 = pool.submit(new MyCallable(300));
        Future<String> f4 = pool.submit(new MyCallable(400));
        Future<String> f5 = pool.submit(new MyCallable(500));

//        String rs = f1.get();
//        System.out.println(rs);
        
        System.out.println(f1.get());
        System.out.println(f2.get());
        System.out.println(f3.get());
        System.out.println(f4.get());
        System.out.println(f5.get());


    }
}
pool-1-thread-1执行1-100子线程执行的结果是:5050
pool-1-thread-2执行1-200子线程执行的结果是:20100
pool-1-thread-3执行1-300子线程执行的结果是:45150
pool-1-thread-3执行1-400子线程执行的结果是:80200
pool-1-thread-3执行1-500子线程执行的结果是:125250

5.Excutors工具类实现线程池

package com.wjh.d8_threadpool;
/*
    目标:使用Executors的工具方法直接得到一个线程池对象

    public static ExecutorService newFixedThreadPool (int nThreads)
    eg:创建固定线程数量的线程池,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程替代它。

 */


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

public class TheadPoolDemo3 {
    public static void main(String[] args) throws Exception{
        //1.创建固定线程数据的线程池
        ExecutorService pool = Executors.newFixedThreadPool(3);

        pool.execute(new MyRunnable() );
        pool.execute(new MyRunnable() );
        pool.execute(new MyRunnable() );

        //已经没有多余线程!
        pool.execute(new MyRunnable() );

    }
}

七.补充知识:定时器

 

package com.wjh.d9_timer;
/*
    目标:timer定时器的使用
 */

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class TimerDemo1 {
    public static void main(String[] args) {
        //1.创建Timer定时器
        Timer timer = new Timer();

        //2.调用方法,处理定时任务
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "执行A1次..." + new Date());
//                try {
//                    Thread.sleep(5000);
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
            }
        },3000,2000);

    timer.schedule(new TimerTask() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "执行B1次..." + new Date());
//            try {
//                System.out.println(10 / 0);
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
        }
    },3000,2000);

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "执行C1次..." + new Date());
            }
        },3000,3000);
    }
    }

package com.wjh.d9_timer;
/*
    目标:timer定时器的使用
 */

import com.wjh.d8_threadpool.MyRunnable;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class TimerDemo2 {
    public static void main(String[] args) {
        //1.创建ScheduledExecutorService线程池,做定时器
        ScheduledExecutorService pool =Executors.newScheduledThreadPool(3);

        //2.开启定时任务
        pool.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "执行输出:AA");
                try {
                    Thread.sleep(100000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },0, 2, TimeUnit.SECONDS);

        pool.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "执行输出:BB");
                //System.out.println(10 / 0);
            }
        },0, 2, TimeUnit.SECONDS);

        pool.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "执行输出:CC");
            }
        },0, 2, TimeUnit.SECONDS);


    }
}

八.补充知识:并发、并行

 

九.补充知识:线程的生命周期

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员希西子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值