Java学习笔记------多线程(七)

该学习笔记是根据阿玮老师《黑马程序员Java零基础视频教程》总结出来的,非常感谢阿玮老师。

一. 什么是线程

  1. 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。进程是程序的基本执行实体(可以理解为一个软件运行就是一个进程,例如运行微信是一个进程,运行QQ也是一个进程,运行浏览器也是一个进程)。进程中有了线程之后,可以同时运行多个功能。
        举个例子:小王是一个伟大的工人(唉,其实就是拧螺丝的),在流水线上负责搬货物,一个流水线上每10分钟出现一个货物,也就是小王在一条流水线上每10分钟搬一次货物。但是他老板嫌弃兰博基尼来的慢,所以就让小王负责6条流水线上的货物,这6条流水线上的货物在10分钟之内都出现。也就是说小王原先10分钟之内只需要搬1次货物,现在小王10分钟之内需要搬6次货物,那么我们就可以把流水线看成是线程,6条流水线相当于6个线程,而小王搬货物这件事就可以看成是一个进程。多线程可以看成小王在10分钟之内搬多个货物,也就是在一个时间内干多件事情。
    多线程
  2. 并发和并行
    并发和并行
    多个线程抢夺CPU是随机的,也就是说该线程随时能抢到CPU资源,随时能失去CPU资源。

二. 多线程的实现方式

  1. 继承Thread类的方式进行实现
public class Test {
    public static void main(String[] args) throws IOException {
        // 多线程的第一种启动方式
        // 1.自己定义一个类继承Thread; 2.重写run方法; 3.创建子类的对象,并启动线程

        // 创建子类对象
        MyThread mt1 = new MyThread();
        mt1.setName("线程1"); // 给线程起名字
        MyThread mt2 = new MyThread();
        mt2.setName("线程2");
        // 启动线程
        mt1.start();
        mt2.start();
    }
}

class MyThread extends Thread{
    @Override
    public void run() {
        //书写线程要执行的代码
        for (int i = 0; i < 6; i++) {
            System.out.println(getName()+"HelloWorld");
        }
    }
}
/*输出:
线程1HelloWorld
线程2HelloWorld
线程1HelloWorld
线程2HelloWorld
线程2HelloWorld
线程2HelloWorld
线程2HelloWorld
线程1HelloWorld
线程2HelloWorld
线程1HelloWorld
线程1HelloWorld
线程1HelloWorld
*/
  1. 实现Runnable接口的方式进行实现
public class Test {
    public static void main(String[] args) throws IOException {
        // 多线程的第二种启动方式
        // 1.自己定义一个类实现Runnable接口; 2.重写run方法; 3.创建自己类的对象; 4.创建一个Thread类对象,并开启线程

        // 创建MyRunnable对象,表示多线程要执行的任务
        MyRunnable mt = new MyRunnable();
        // 创建线程对象
        Thread t1 = new Thread(mt);
        Thread t2 = new Thread(mt);
        //给线程设置名字
        t1.setName("线程1");
        t2.setName("线程2");
        // 开启线程
        t1.start();
        t2.start();
    }
}

class MyRunnable implements Runnable{
    @Override
    public void run() {
        //书写线程要执行的代码
        for (int i = 0; i < 6; i++) {
            // 获取当前线程的对象
            Thread t = Thread.currentThread();
            System.out.println(t.getName()+"HelloWorld");
        }
    }
}
/*输出:
线程2HelloWorld
线程1HelloWorld
线程2HelloWorld
线程1HelloWorld
线程2HelloWorld
线程2HelloWorld
线程2HelloWorld
线程2HelloWorld
线程1HelloWorld
线程1HelloWorld
线程1HelloWorld
线程1HelloWorld
*/
  1. 利用Callable接口和Future接口的方式进行实现
public class Test {
    public static void main(String[] args) throws IOException, ExecutionException, InterruptedException {
        // 多线程的第三种实现方式
        // 1.自己定义一个类MyCallable实现Callable接口; 2.重写call方法(有返回值,表示多线程运行的结果);
        // 3.创建MyCallable类的对象(表示多线程要执行的任务); 4.创建FutureTask的对象(作用是管理多线程运行的结果)
        // 5.创建Thread对象,并启动(表示线程)

        // 创建MyCallable类的对象
        MyCallable mc = new MyCallable();
        //创建FutureTask的对象
        FutureTask<Integer> ft = new FutureTask<>(mc);
        // 创建Thread对象
        Thread t1 = new Thread(ft);
        // 启动线程
        t1.start();
        int sum = ft.get();
        System.out.println(sum);
    }
}

class MyCallable implements Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        //计算前100个数的和
        int sum = 0;
        for (int i = 1; i <=100 ; i++) {
            sum = sum+i;
        }
        return sum;
    }
}
/*
输出:
5050
*/
  1. 三种实现方式的比较
    比较
  2. Thread类中常见的成员方法
    成员方法

三. 线程同步的方式

  1. 同步代码块中synchronized后面的锁对象一定要是唯一的(通常是synchronized (MyThread.class))。
    同步代码块
  2. 同步方法就是把synchronized关键字加到方法上。同步方法
  3. 手动上锁–Lock锁
    上锁

四. 等待唤醒机制

  1. 等待唤醒机制也叫做生产者和消费者。下面使用吃货(消费者)和厨师(生产者)做个比喻,如下图所示。
    生产者与消费者
  2. 生产者和消费者常见的方法
    方法
  3. 阻塞队列实现等待唤醒机制,生产者和消费者必须使用同一个阻塞队列。
    阻塞队列
    阻塞队列的继承结构
  4. 线程的状态
    线程状态
    虽然上图中展示了7种状态,但java虚拟机没有定义"运行"转态,所以只有以下6种状态。
    在这里插入图片描述

五. 线程池

  1. 线程池原理
    线程池原理
  2. 线程池的代码实现:首先创建线程池;其次提交任务;最后所有的任务全部执行完毕,关闭线程池。
    在这里插入图片描述
    代码实现
public class Test {
    public static void main(String[] args) throws IOException {
        // 1.创建线程池对象pool1
        ExecutorService pool1 = Executors.newCachedThreadPool();
        ExecutorService pool2 = Executors.newFixedThreadPool(2); //这个线程池只能存放2个线程

        // 2.提交任务
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());

        pool2.submit(new MyRunnable());
        pool2.submit(new MyRunnable());
        pool2.submit(new MyRunnable());
        pool2.submit(new MyRunnable());
        // 销毁线程池
        pool1.shutdown();
        pool2.shutdown();
    }
}

class MyRunnable implements Runnable{
    @Override
    public void run() {
        int sum = 0;
        for (int i = 0; i < 100; i++) {
            sum = sum+i;
        }
        System.out.println(Thread.currentThread().getName()+":  "+sum);
    }
}
输出:
pool-1-thread-1:  4950
pool-1-thread-4:  4950
pool-2-thread-1:  4950
pool-1-thread-2:  4950
pool-2-thread-2:  4950
pool-1-thread-6:  4950
pool-2-thread-1:  4950
pool-2-thread-1:  4950
pool-1-thread-5:  4950
pool-1-thread-3:  4950
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值