【Java基础24】进程、线程、生产者-消费者模型

一、进程

1、进程概念

进程是程序在处理机上的一次执行过程,是动态的。进程是一个具有一定独立功能的程序,一个实体,每个进程都有它自己的地址空间。

进程的状态:运行状态、就绪状态、阻塞状态。

二、线程

1、线程概念

一个进程可以划分为若干个线程,线程是进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行,一个进程最少有一个线程。

并行:两个进程同时运行

并发:宏观同时,微观分时。

线程实现的两种方式:继承Thread类,实现Runnable接口

import sun.font.FontRunIterator;

public class Test01 {
    public static void main(String[] args){
        Mythread mt=new Mythread();
        mt.start();//启动线程,虚拟机启动

        MyRunnable mr=new MyRunnable();
        Thread t=new Thread(mr);
        t.start();
    }
}
//实现线程的第一种方式
class Mythread extends Thread{
    public void run(){
        for (int i = 0; i < 50; i++) {
            System.out.println("当前线程的名字:"+Thread.currentThread().getName()+" "+i);
        }
    }
}

//实现线程的第二种方式,推荐使用
class MyRunnable implements Runnable{
    public void run(){
        for (int i = 0; i < 50; i++) {
            System.out.println("当前线程的名字:"+Thread.currentThread().getName()+" "+i);
        }
    }
}

2、线程休眠、join、中断

线程休眠可以释放CPU时间片。

 MyRunnable mr=new MyRunnable();
Thread t=new Thread(mr);
t.setDaemon(true);//把线程设置为守护线程,线程分为守护线程和用户线程,当程序中没有用户线程时JVM会退出
t.start();

for (int i = 0; i < 50; i++) {
    System.out.println("当前线程的名字:"+Thread.currentThread().getName()+" "+i);
    /* try {
                Thread.sleep(300);//线程休眠释放时间片
            } catch (InterruptedException e) {
                e.printStackTrace();
                Thread.currentThread().interrupt();
            }*/
    if(i==20){
        try {
            t.join();//让t线程执行完毕再执行主线程
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


    }
}

3、线程同步

import java.util.concurrent.locks.ReentrantLock;

public class Test01 {
    public static void main(String[] args) {
        MyRunnable1 my1=new MyRunnable1();
        Thread t1=new Thread(my1);
        Thread t2=new Thread(my1);
        t1.start();
        t2.start();
    }
}

//多线程共享数据时,产生线程不安全现象,比如两个窗口售票,一个票只能售出一次,解决多线程不安全,引入线程同步,会牺牲性能换取线程安全
//实现同步的三种方法:同步代码块,同步方法,lock
class MyRunnable1 implements Runnable{
    private int ticket=10;
//    private Object obj=new Object();
    public void run(){
        for (int i = 0; i < 300; i++) {
            /*if (ticket > 0) {
                synchronized (this) {//同步代码块,括号里是同步的对象,任意一个对象,相当于上锁
                    ticket--;
                    System.out.println("您购买的票剩余" + ticket + "张");
                    try {
                        Thread.sleep(1000);//不释放锁
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }*/
//            method();//同步方法
            method1();
        }
    }
//同步方法
    private synchronized void method(){
        if (ticket > 0) {
            synchronized (this) {//同步代码块,括号里是同步的对象,任意一个对象,相当于上锁
                ticket--;
                System.out.println("您购买的票剩余" + ticket + "张");
                try {
                    Thread.sleep(1000);//不释放锁
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //互斥锁
    ReentrantLock lock=new ReentrantLock();
    private  void method1() {
        lock.lock();//上锁
        try {
            if (ticket > 10) {
                ticket--;
                System.out.println("您购买的票剩余" + ticket + "张");
                try {
                    Thread.sleep(1000);//不释放锁
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }finally {
            lock.unlock();//解锁
        }
    }
}

同步准则:

(1)使代码块保持简短,不把随线程变化的预处理和后处理移出synchronized块。

(2)不要阻塞。

(3)在持有锁的时候,不要对其他对象调用同步方法。

4、线程死锁

多线程中要进行资源共享,就要进行同步,但同步过多会造成死锁。死锁一般在程序运行时才有可能出现。

5、线程池

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Test02 {
    public static void main(String[] args) {
        //创建线程池
//            ExecutorService es=Executors.newSingleThreadExecutor();//创建单线程
//            ExecutorService es=Executors.newFixedThreadPool(3);//创建3个线程
        //以上两种使用较多
//         ExecutorService es=Executors.newCachedThreadPool();//创建一个可缓存的线程池,不会对线程池大小做限制
        ScheduledExecutorService es= Executors.newScheduledThreadPool(3);//创建一个无限大小的线程池


//            es.execute(new MyRunnable());//执行任务,使用单个线程执行
//            es.execute(new MyRunnable());//多线程使用另一个线程执行
            es.schedule(new MyRunnable(),1000, TimeUnit.MILLISECONDS);//延迟一秒执行
            es.shutdown();//结束


    }
}

class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"-------"+i);
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

三、生产者-消费者模型

public class Test01 {
    public static void main(String[] args) {
        Food f=new Food();
        Producter p=new Producter(f);
        Consumer c=new Consumer(f);
        Thread t1=new Thread(p);
        Thread t2=new Thread(c);
        t1.start();
        t2.start();
    }
}

class Producter implements Runnable{
    private Food food;
    public Producter(Food food) {
        this.food = food;
    }
    public void run() {
        for (int i = 0; i < 20; i++) {
            if(i%2==0){
                food.set("可乐鸡翅","酸酸甜甜");
            }else{
                food.set("糖醋排骨","口感鲜美");
            }
        }
    }
}

class Consumer implements Runnable{
    private Food food;
    public Consumer(Food food) {
        this.food = food;
    }
    public void run() {
        for (int i = 0; i < 20; i++) {
            food.get();
        }
    }
}

class Food{
    private String name;
    private String special;
    private boolean flag=true;//true表示生产,false表示消费

    public Food(String name, String special) {
        this.name = name;
        this.special = special;
    }
//生产的方法
    public synchronized void set(String name,String special) {
        if (!flag) {//不能生产
            try {
                this.wait();//线程进入等待状态,释放监视器的所有权(Object类的方法)
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.setName(name);//可以生产
        try {
            Thread.sleep(500);//线程休眠,不释放监视器的所有权
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.setSpecial(special);//生产结束
        flag=false;//不能生产
        this.notify();//唤醒线程
    }
    //消费的方法
    public synchronized void get(){
        if(flag){//不能消费
            try {
                this.wait(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {//可以消费
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(this.getName()+"---->"+this.getSpecial());//消费结束
        flag=true;//不能消费
        this.notify();//唤醒一个线程
//        this.notifyAll();//唤醒所有线程
    }

    @Override
    public String toString() {
        return "Food{" +
                "name='" + name + '\'' +
                ", special='" + special + '\'' +
                '}';
    }

    public Food() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSpecial() {
        return special;
    }

    public void setSpecial(String special) {
        this.special = special;
    }
}

sleep和wait的区别:

sleep:让线程休眠,让出CPU的时间片,但是不释放监视器的所有权(对象锁)。

wait:让线程进入等待状态,让出CPU的时间片,释放监视器的所有权(Object类的方法),等待其他线程通过notify方法来唤醒。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值