JAVA多线程

1、进程和线程

①是什么?
答:
1、进程:是并发执行的程序在执行过程中进行系统资源分配和调度的基本单位。
2、线程:线程是进程的执行单元,比进程更小的独立运行的基本单位。也被成为轻量级进程。
②、进程和线程的区别?
答:
进程是享有独立的地址空间,而同一进程的线程共享本进程的地址空间。一个进程崩溃不会影响其它的进程;而一个进程中的某个线程崩溃会导致进程崩溃,从而使本进程的其它线程崩溃。多进程中的资源是不能共享的,而一个进程中的多个线程资源共享。

2、线程的生命周期

①新生态(new):一个线程对象实例化完成,还没有做任何操作
②就绪态(ready):一个线程已经被开启,已经开始争抢CPU时间片
③运行态(run):一个线程抢到了CPU时间片,开始执行线程中的逻辑。
④阻塞态(Interrupt):一个线程执行过程中,受到某些操作的影响,放弃了已经获取的CPU时间片,并且不再参与时间片的争抢,此时线程处于挂起状态。
⑤死亡态(Dead):一个线程需要被销毁。

在这里插入图片描述

3、创建线程的两种方式(继承Thread类,实现Runnable接口)

package cn.cduestc.thread;

public class ThreadTest {

    public static void main(String[] args) {

        //第一种方式:继承Thread类的方式
        MyThread t1 = new MyThread();
        /**
         *  调用start方法,使线程进入就绪状态
         *      这里必须调用start方法,只有调用start方法才会创建新的线程
         *      如果直接调用run方法,那只是本线程执行了run方法而已,并没有创建新的线程
         */
        t1.start();

        //第二种方式:实现Runnable接口
        /*Runnable r1 = new Runnable() {
            @Override
            public void run() {
                for (int i = 0;i <1000;i++){
                    System.out.println("实现runnable类方式实现多线程:"+i);
                }
            }
        };*/

        //使用lambda表达式
        Runnable r1 = ()->{
            for (int i = 0;i <1000;i++){
                System.out.println("实现runnable类方式实现多线程:"+i);
            }
        };

        Thread t2 = new Thread(r1);
        t2.start();

    }
}

class MyThread extends Thread {

    @Override
    public void run() {
        for (int i = 0;i <1000;i++){
            System.out.println("继承Thread类方式实现多线程:"+i);
        }
    }
}

4、线程的命名、睡眠、优先级

package cn.cduestc.thread;

public class ThreadTest2 {

    public static void main(String[] args) {

        //test1();
        test2();

    }

    public static void test2(){
        Runnable r = new Runnable(){
            @Override
            public void run() {
                for (int i = 0;i < 10;i++){
                    if(i == 3){
                    	//线程礼让指让当前运行状态的线程释放自己的CPU资源,从运行态回到就绪态
                        Thread.yield();
                    }
                    System.out.println(Thread.currentThread().getName()+":"+i);
                }
            }
        };
        Thread t1 = new Thread(r,"线程一");
        Thread t2 = new Thread(r,"线程二");
        t1.start();
        t2.start();
    }

    public static void test1(){
        //线程的命名、睡眠、优先级
        /**
         *  设置线程优先级只是修改线程抢道CPU时间片的概率
         *  优先级的设置等级是[0,10]的整数,默认是5
         */
        MyThread2 t1 = new MyThread2("线程一");
        MyThread2 t2 = new MyThread2("线程二");

        //优先级的设置必须在start方法调用之前
        t1.setPriority(1);
        t2.setPriority(10);

        t1.start();
        t2.start();
    }

}

class MyThread2 extends Thread{
    public MyThread2(){}
    public MyThread2(String name){
        //super(name);
        this.setName(name);
    }

    @Override
    public void run() {
        for (int i=0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

5、同步代码段的方式解决这一问题

package cn.cduestc.thread;

public class SynchronizedDemo {

    public static void main(String[] args) {

        Runnable r = new Runnable() {
            @Override
            public void run() {
                /**
                 *  对象锁:括号中添加的是一个不变的对象 如:""
                 *  类锁:括号添加的是一个类的字节码对象 如:SynchronizedDemo.class
                 *  重点:括号中的对象必须是一个固定的  不能是类似 new SynchronizedDemo(),因为不同的线程访问每次都会创建一个不同的对象
                 */
                //同步代码段
                while (ticket.num > 0){
                    synchronized (""){
                        if(ticket.num <= 0){
                            return;
                        }
                        System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+ --ticket.num +"张");
                    }
                }
            }
        };

        Thread t1 = new Thread(r,"甲");
        Thread t2 = new Thread(r,"乙");
        Thread t3 = new Thread(r,"丙");
        Thread t4 = new Thread(r,"丁");

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

class ticket {
    public static int num = 100;
}

6、同步方法解决问题

package cn.cduestc.thread;

public class SynchronizedDemo2 {

    public static void main(String[] args) {

        Runnable r = new Runnable() {
            @Override
            public void run() {
                while (ticket2.num > 0){
                    ticket2.sell();
                }
            }
        };

        Thread t1 = new Thread(r,"甲");
        Thread t2 = new Thread(r,"乙");
        Thread t3 = new Thread(r,"丙");
        Thread t4 = new Thread(r,"丁");

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}
class ticket2 {
    public static int num = 100;

    /**
     *  同步方法:
     *      如果是静态方法,那么同步锁是类锁,当前类.class;
     *      如果是非静态方法,那么同步锁是this
     */
    public synchronized static void sell(){
        if (num <= 0){
            return;
        }
        --num;
        System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+num+"张");
    }
}

7、使用ReentrantLock锁解决问题

package cn.cduestc.thread;

import java.util.concurrent.locks.ReentrantLock;

public class LockDemo {

    public static void main(String[] args) {

        ReentrantLock lock = new ReentrantLock();
        Runnable r = new Runnable() {
            @Override
            public void run() {
                while (ticket2.num > 0){
                    lock.lock();
                    if(ticket2.num <= 0){
                        lock.unlock();
                        return;
                    }
                    System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+ --ticket2.num +"张");
                    lock.unlock();
                }
            }
        };

        Thread t1 = new Thread(r,"甲");
        Thread t2 = new Thread(r,"乙");
        Thread t3 = new Thread(r,"丙");
        Thread t4 = new Thread(r,"丁");

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

8、死锁

package cn.cduestc.thread;

public class DieLock {
    public static void main(String[] args) {
        Runnable r1 = () -> {
            synchronized ("A") {
                System.out.println("甲持有了A锁,等待B锁");
                synchronized ("B") {
                    System.out.println("甲持有了A锁和B锁");
                }
            }
        };

        Runnable r2 = () -> {
            synchronized ("B") {
                System.out.println("乙持有了B锁,等待A锁");
                synchronized ("A") {
                    System.out.println("乙持有了A锁和B锁");
                }
            }
        };

        Thread t1 = new Thread(r1);
        Thread t2 = new Thread(r2);
        t1.start();
        t2.start();
    }
}

9、解决死锁问题(使用wait,notify,notifyAll)

package cn.cduestc.thread;

public class DieLock2 {
    public static void main(String[] args) {
        Runnable r1 = () -> {
            synchronized ("A") {
                System.out.println("甲持有了A锁,等待B锁");
                /**
                 *   wait:等待,是Object中的一个方法,当前线程释放自己的锁标记,并且让出CPU资源,使得该线程进入等待队列中
                 *   notify:通知,是Object中的一个方法,唤醒等待队列中的一个线程,使得线程进入锁池
                 *   notifyAll:通知,是Object中的一个方法,唤醒持有该锁标记的所有线程,并使得这些线程进入锁池
                 */
                try {
                    "A".wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized ("B") {
                    System.out.println("甲持有了A锁和B锁");
                }
            }
        };

        Runnable r2 = () -> {
            synchronized ("B") {
                System.out.println("乙持有了B锁,等待A锁");
                synchronized ("A") {
                    System.out.println("乙持有了A锁和B锁");
                    "A".notifyAll();
                }
            }
        };

        Thread t1 = new Thread(r1);
        Thread t2 = new Thread(r2);
        t1.start();
        t2.start();
    }
}

10、生产者消费者模式

①产品(Product)
package cn.cduestc.productorAndConsumer;

public class Product {
    private String name;
    public Product(String name){
        this.name = name;
    }
    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
}
②产品池(ProductPool)
package cn.cduestc.productorAndConsumer;

import java.util.ArrayList;
import java.util.List;

public class ProductPool {

    //用于存放商品的List集合
    private List<Product> productList;
    //产品池中最大的产品数量
    private int maxSize = 0;

    //构造方法
    public ProductPool (int maxSize){
        this.productList = new ArrayList<Product>(15);
        this.maxSize = maxSize;
    }

    //生产者生产商品过后将商品放入产品池
    public synchronized void push(Product product){
        //判断如果产品池中产品数量达到了最大容量,那么该线程进入等待状态
        if(this.productList.size() == maxSize){
            try {
                //因为访问的临界资源是产品池,即该类对象,所以这里使用this
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.productList.add(product);
        //产品添加成功,唤醒其他线程
        this.notifyAll();
    }

    //消费者消费产品
    public synchronized Product pop(){
        //判断是否还有产品
        if(this.productList.size() == 0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //消费产品,每次取出集合中的第一个产品
        Product product = this.productList.remove(0);
        //唤醒其他线程
        this.notifyAll();
        return product;
    }
}
③生产者(Productor):这里使用的是死循环
 package cn.cduestc.productorAndConsumer;

public class Productor extends Thread {

    private ProductPool productPool;
    public Productor(ProductPool productPool){
        this.productPool = productPool;
    }
    @Override
    public void run() {
        while(true){
            String name = (int)(Math.random()*100)+"号产品";
            Product product = new Product(name);
            this.productPool.push(product);
            System.out.println("生产者了一个产品:"+name);
        }
    }
}
④消费者(Consumer):这里也是使用死循环
package cn.cduestc.productorAndConsumer;

public class Consumer extends Thread {

    private ProductPool productPool;
    public Consumer(ProductPool productPool){
        this.productPool = productPool;
    }
    @Override
    public void run() {
        while (true){
            Product product = this.productPool.pop();
            System.out.println("消费者消费了一个产品:"+product.getName());
        }
    }
}
⑤测试代码
package cn.cduestc.productorAndConsumer;

public class Program {

    public static void main(String[] args) {

        ProductPool productPool = new ProductPool(15);
        new Productor(productPool).start();
        new Consumer(productPool).start();

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值