复习整理的DAY16_线程

什么是线程?

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。是CPU调度和分派的基本单位,本身不拥有系统资源,但可以访问进程的系统资源。

老生常谈的一个问题:线程和进程之间的关系?

(1)一个线程只属于一个进程,一个进程可以有多个线程,至少有一个线程(一般称为主线程)。

(2)资源分配给进程,同一个进程的所有线程共享该进程的资源。

(3)线程在执行过程中,协作同步。

(4)CPU分配给线程。真正在CPU上运行的是线程。

(5)线程是进程的可执行单元,是进程的可调度实体。

创建线程的方式(Java):

(1)继承Thread

举例:

public class Test extends Thread{

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
        }
    }
}
public class TestThread {

    public static void main(String[] args) {
        Test test = new Test();
        test.start();
    }
}

(2)实现Runnable接口

举例:

public class Test implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " : " + i);
        }
    }
}
public class TestThread {

    public static void main(String[] args) {
        Test test = new Test();
        Thread thread = new Thread(test);
        thread.start();
    }
}

两种方式比较:第一种是单继承,该类继承了Thread继承了Thread后,后续无法再继承其他类,只能实现接口,第二种是实现接口,不影响后续的继承与实现。

线程可能会发生的问题:

比如:A和B同时从银行取钱,总额为5000,A取3000,B也取3000,由于线程同步,两者都能取到钱,最后剩余钱为-1000。这显然是不正确的。

这种时候,需要加锁。

举例:吃蛋糕

public class Cake {
    // 蛋糕的编号
    private String name;

    public Cake(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Cake{" +
                "name='" + name + '\'' +
                '}';
    }
}
public class Panzi {
    // 只在头部移除removeFirst,只在尾部添加addLast
    private LinkedList<Cake> list = new LinkedList<>();

    public synchronized void putCake(Cake cake) {// 加锁
        list.addLast(cake);
        notifyAll();// 唤醒全部线程
        System.out.println("生产者线程 putCake notifyAll");
    }
    public synchronized Cake getCake() {// 加锁
        if (list.size() <= 0) {     // 盘子里面没有蛋糕,所以要wait等待
            try {
                System.out.println("消费者线程 getCake wait");
                wait();// 是java.lang.Object里面的方法
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return list.removeFirst();
    }
}
public class ProducerThread extends Thread{
    private Panzi panzi;

    public ProducerThread(String name, Panzi panzi) {
        super(name);// 给当前线程命名
        this.panzi = panzi;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            Cake cake = new Cake("no:" + i);
            System.out.println(Thread.currentThread().getName() + " putCake: " + cake);
            // 生产一个蛋糕就放到盘子里面
            panzi.putCake(cake);

            // 1000毫秒就是1秒
            // 生成随机等待的时间,模拟生成蛋糕的过程
            try {
                Thread.sleep(new Random().nextInt(5000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class ConsumerThread extends Thread{
    private Panzi panzi;

    public ConsumerThread(String name, Panzi panzi) {
        super(name);
        this.panzi = panzi;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            Cake cake = panzi.getCake();
            System.out.println(Thread.currentThread().getName() + " getCake : " + cake);

            // 生成随机等待的时间,模拟吃蛋糕的过程
            try {
                Thread.sleep(new Random().nextInt(5000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class Main {// 主函数
    public static void main(String[] args) {
        // 生产者消费者操作的是同一个盘子
        Panzi panzi = new Panzi();
        // 启动生产者线程去生产蛋糕
        ProducerThread producerThread = new ProducerThread("生产者线程",panzi);
        producerThread.start();
        // 启动消费者线程去吃蛋糕
        ConsumerThread consumerThread = new ConsumerThread("消费者",panzi);
        consumerThread.start();
    }
}

线程的基本状态:

首先,如图:

 注:最上面两个锁池和等待队列也可以归为阻塞状态中。

1)新建状态:创建了一个线程对象

2)可运行状态(就绪状态):线程对象创建后,该对象的start方法已经被其他线程调用了,所以只能在可运行线程池(等待队列)中等待被调度,获得CPU的使用权;原本是运行状态,但是时间片用完了;在运行状态中调用了yield方法,转为可运行状态;原本处于阻塞状态,解决了阻塞的原因,转为可运行状态。

3)运行状态:原本在可运行状态,获得了CPU的时间片,执行程序

4)阻塞状态:由于某种原因,让出了CPU的时间片,暂时停止运行。

5)死亡状态:线程的run或main方法结束,或者出现异常退出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值