Java基础篇(七)

1.进程

是一个独立运行的应用程序

​ 比如电脑软件,启动之后,就是一个进程,需要系统进行的分配,可以获取当前系统内存,网卡,显卡等。

​ 1.独立性

​ 各个进程之间是互相独立的,互不影响的。

​ 2.互斥性

​ 每个应用程序(软件) 系统分配一个独立的端口号

​ 写代码 Demo1 里面 main主函数 Demo1可以看成一个应用程序 就是一个进程

2.线程

进程是由至少一个或者多个线程组成的。

线程是进程最小的基本单位。

特性:
1.抢占式运行【重要】
	给程序 分配CPU,按照时间片来执行,单位时间片抢占式执行的。随机抢占的

2.资源共享
	同一个进程,有多个线程,这个多个线程是可以共享同一个数据的
	Java程序:Demo1可以看成一个进程,一个Java程序中有两个线程:
		1.main 主线程
		2.垃圾回收的线程

面试题:进程和线程的区别

1、调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位。
2、并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行。
3、拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程
的资源。
4、系统开销:在创建或撤销进程的时候,由于系统都要为之分配和回收资源,导致系统的明显
大于创建或撤销线程时的开销。但进程有独立的地址空间,进程崩溃后,在保护模式下不会对其
他的进程产生影响,而线程只是一个进程中的不同的执行路径。线程有自己的堆栈和局部变量,
但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多
线程的程序健壮,但是在进程切换时,耗费的资源较大,效率要差些。

3.并行和并发

并行:真正的同时执行

并发:同时发生,轮流交替执行

4.创建线程的两种方式

Java虚拟机允许应用程序同时执行多个执行线程。

创建线程的第一种:

​ 创建一个新的执行线程有两种方法。一个是将一个类声明为Thread的子类(继承Thread)。这个子类应该重写run方法,然后可以分配并启动子类的实例。

package com.qf.Day23;

class MyThread1 extends Thread {
    //重写run方法
    @Override
    public void run() {
        //这个线程中打印10次的MyThread1线程:
        for (int i = 0; i < 9; i++) {
            System.out.println("线程:" + i);
        }
    }
}

public class Demo4 {
    public static void main(String[] args) {
        MyThread1 myThread1 = new MyThread1();
        //启动线程
        new Thread(myThread1).start();
        for (int i = 0; i < 100; i++) {
            System.out.println("main主线程" + i);
        }
    }
}

练习:新建两个线程,一个县城打印99乘法表,另一个线程打印直角三角形

package com.qf.a_thread;

class MyThread3 extends Thread {
    @Override
    public void run() {
        for (int i = 1; i < 10; i++) {
            for (int j = 1; j <= i; j++) {
                System.out.print(j + "*" + i + "=" + i*j + "\t");
            }
            System.out.println();
        }
    }
}
class MyThread4 extends Thread {
    @Override
    public void run() {
        for (int i = 1; i < 10 ; i++) {
            for (int j = 1; j <= i; j++) {
                System.out.print("*");
            }
            System.out.println();
        }
    }
}
public class Demo2 {
    public static void main(String[] args) {
        new MyThread3().start();
        new MyThread4().start();
    }
}

第二种创建方式:

另一种方法来创建一个线程是声明实现类Runnable接口。 那个类然后实现了run方法。 然后可以分配类的实例,在创建Thread时作为参数传递,并启动。

package com.qf.b_thread;

class MyThread1 implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("MyThread1:" + i);
        }
    }
}
class MyThread2 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("MyThread2:" + i);
        }
    }
}
public class Demo1 {
    public static void main(String[] args) {
        MyThread1 myThread1 = new MyThread1();
        MyThread2 myThread2 = new MyThread2();
        //在创建Thread时作为参数传递并启动。
        new Thread(myThread1).start();
        new Thread(myThread2).start();
    }
}

练习:新建两个线程,一个线程打印99乘法表,另外一个线程打印直接三角形

package com.qf.b_thread;


class MyThread3 implements Runnable {
    @Override
    public void run() {
        for (int i = 1; i < 10 ; i++) {
            for (int j = 1; j <= i; j++) {
                System.out.print("*");
            }
            System.out.println();
        }
    }
}
class MyThread4 implements Runnable {
    @Override
    public void run() {
        for (int i = 1; i < 10; i++) {
            for (int j = 1; j <= i; j++) {
                System.out.print(j + "*" + i + "=" + i*j + "\t");
            }
            System.out.println();
        }
    }
}
public class Demo3 {
    public static void main(String[] args) {
        //然后可以分配类的实例,在创建Thread时作为参数传递,并启动。
        new Thread(new MyThread3()).start();
        new Thread(new MyThread4()).start();
    }
}

5.死锁

开发中禁止出现死锁

面试题:

​ 应用场景:并发场景,多个线程。线程之间在共享数据的时候是互不相让的

线程加锁是为了线程安全

死锁是一种状态,当两个线程互相持有对象所需要的资源的时候,这两个线程又都不主动释放资源。

就会导致死锁。代码无法正常执行。这两个线程就会僵持住。

package com.qf.review;

class DeadLock implements Runnable {//实现Runnable接口
    private boolean flag;//标记
    private Object obj1;//对象1
    private Object obj2;//对象2

    public DeadLock(boolean flag, Object obj1, Object obj2) {//构造函数
        this.flag = flag;
        this.obj1 = obj1;
        this.obj2 = obj2;
    }
    //重写run方法
    @Override
    public void run() {
        if (flag) {//如果flag = true 让线程1执行这个if语句里面的代码
            synchronized (obj1) {
                System.out.println(Thread.currentThread().getName() + "拿到了obj1资源");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程1执行了");
                synchronized (obj2) {//锁obj2的前提是先有obj2资源
                    //想用obj2这个资源,但是下面未释放obj1,所以就停了,导致obj2也未释放掉
                    System.out.println(Thread.currentThread().getName() + "拿到obj2资源");
                }
            }
        }
        if (!flag) {//如果flag=false 线程2 执行这个if语句里面的代码
            synchronized (obj2) {
                System.out.println(Thread.currentThread().getName() + "拿到了obj2资源");
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程2执行了");
                synchronized (obj1) {//不自动释放
                    //想用obj1这个资源,但是上面未释放obj2,所以就停了,导致obj1也未释放掉
                    System.out.println(Thread.currentThread().getName() + "拿到obj1资源");
                }
            }
        }
    }
}

public class Review20 {
    public static void main(String[] args) {
        Object obj1 = new Object();
        Object obj2 = new Object();
        DeadLock deadLock1 = new DeadLock(true, obj1, obj2);
        new Thread(deadLock1, "线程1").start();
        DeadLock deadLock2 = new DeadLock(false, obj1, obj2);
        new Thread(deadLock2, "线程1").start();
    }
}

6.Object类下面的和线程相关的方法

public final void wait(){
		throws InterruptedException
}

导致当前线程等待,直到另一个线程调用该对象notify()方法或者notifyAll()方法。

总结:至少两个线程,对象.wait(),那么当前线程就会阻塞。阻塞就是这个线程暂时不执行了。如何让这个线程继续执行下去呢?再开另外一个线程,对象.notify()去唤醒另外一个线程!!!

wait1线程正在等待中....
唤醒线程已经执行
wait1线程被唤醒!!!Line45行的
我是修改之后的message对象
wait2线程正在等待中....
package com.qf.review;
class Message{//先创建类,再创建对象,再调用wait方法
    private String message;

    public Message(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
//线程类
class WaitThread implements Runnable {
    private Message message;//使用message这个对象,调用wait方法  message.wait()

    public WaitThread(Message message) {//构造方法
        this.message = message;
    }

    //等待线程抢到了
    //等待线程睡了5秒  然后唤醒线程执行。  synchronized (message)
    //message  对象从等待池中国去取的,结果发现没有  阻塞
    //回到等待线程睡醒了以后开始   wait等待
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + "正在等待中....");

        synchronized (message) {
            try {

                //当调用wait方法的时候,synchronized会自动释放锁,(并将对象放到等待池中),让唤醒线程锁来操作这个对象,然后message对象会放到等待池中
                //
                message.wait();//代码走到这一步 当前线程会等待!!!直到被唤醒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name + "被唤醒!!!Line45行的");
            System.out.println(message.getMessage());
        }
    }
}
    //唤醒线程
    class NotifyThread implements Runnable {
        private Message message;

        public NotifyThread(Message message ) {
            this.message = message;
        }
        @Override public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("唤醒线程已经执行");
            synchronized (message) {
                message.setMessage("我是修改之后的message对象");
                //message.notify();
                message.notifyAll();
            }
        }
    }
public class Review21 {
    public static void main(String[] args) {
        Message message = new Message("我是message对象");
        WaitThread waitThread = new WaitThread(message);
        WaitThread waitThread1 = new WaitThread(message);
        NotifyThread notifyThread = new NotifyThread(message);
        new Thread(waitThread1, "wait2线程").start();
        new Thread(waitThread, "wait1线程").start();
        new Thread(notifyThread, "notify线程").start();
    }
}
总结:
新建两个线程:
	一个是等待线程:
		等待线程中代码从上往下执行,但是使用object.wait()方法以后,咱们当前的线程就等待了,到wait之后代码暂时不会往下执行了,需要借助于另外一个线程进行唤醒。
	一个是唤醒线程:
		唤醒线程使用object.notify方法去讲等待线程中的正在等待的线程进行唤醒,让等待线程继续往下执行。
wait和notify方法,实现线程之间的通信问题。
wait2线程正在等待中....
wait1线程正在等待中....
唤醒线程已经执行
wait1线程被唤醒!!!Line45行的
我是修改之后的message对象
wait2线程被唤醒!!!Line45行的
我是修改之后的message对象

7.join方法【开发不用】

为啥join方法放在wait方法之后讲,因为join方法的底层是wait()方法

作用:让主线程等待,一直等待他的子线程执行完以后,才执行主线程

package com.qf;

//创建子线程类
class MyTh implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            String name = Thread.currentThread().getName();
            System.out.println(name + "线程执行了");
        }
    }
}

public class Demo24 {
    public static void main(String[] args) throws InterruptedException {
       /* MyTh myTh=new MyTh();
        Thread thread=new Thread(myTh);*/
        Thread thread=new Thread(new MyTh());
        thread.start();
        thread.join();//让主线程等待,一直等待他的子线程执行完以后,才执行主线程,秒数在join中是无用的
        for (int i = 0; i < 100; i++) {
            String name=Thread.currentThread().getName();
            System.out.println(name + "线程执行了");
        }
    }
}

主线程和子线程是相对而言的。

package com.qf.Day24;

class FatherTherad implements Runnable{

    @Override
    public void run() {
        //SonThread线程是在FatherTherad线程中启动的,那就意味着SonThread是FatherTherad的子线程
        Thread thread = new Thread(new SonThread());
        thread.start();
        //thread的父线程等待,先执行子线程
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 1000; i++) {//join要先进行操作
            System.out.println("父线程" + i);
        }
    }
}
class SonThread implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.err.println("子线程" + i);
        }
    }
}
public class Demo2 {
    public static void main(String[] args) {
        //在父线程中只需要
        //互相套着调用
        new Thread(new FatherTherad()).start();
    }
}

面试题:如何控两个线程的执行顺序?

1、sleep方法使一个线程先睡会,先执行另外一个线程

2、join,让子线程先执行完,在执行父线程

3、线程池

8.生产者消费者模式

生活中的案例:

​ 卖家:汽车厂商

​ 买家:群众

​ 小明想买一个BYD汉,电车定完以后需要等待。

​ 小明告知汽车厂商我要买车,如果又,直接发货。如果没有,小明会纳入等待状态。等汽车厂商生产好以后,唤醒小明的等待线程。然后等待小明来买车。如果没有人买车。汽车会进入到等待状态。如果有人来买车,立马唤醒汽车厂商线程,让他赶紧造车。

生产者:汽车厂商

消费者:小明
在这里插入图片描述

入门案例:

package com.qf.day25;

//生产者消费者模式   Customer   Productor
//goods类,两个线程的共享资源
class Goods {//共享资源
    private String name;
    private double price;
    private boolean isProductor;//代表是否需要生产,true  生产    false  表示不需要生产

    public Goods(String name, double price, boolean isProductor) {
        this.name = name;
        this.price = price;
        this.isProductor = isProductor;
    }

    public String getName() {
        return name;
    }

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

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public boolean isProductor() {
        return isProductor;
    }

    public void setProductor(boolean productor) {
        isProductor = productor;
    }
}

//消费者线程
class Customer implements Runnable {
    private Goods goods;

    public Customer(Goods goods) {
        this.goods = goods;
    }

    @Override
    public void run() {
        while (true) {
            //上锁
            synchronized (goods) {
                if (!goods.isProductor()) {//表示不需要生产
                    System.out.println("消费者购买的是" + goods.getName() + "价格是" + goods.getPrice());
                    //把标记变成true
                    goods.setProductor(true);
                    //唤醒生产者
                    goods.notify();
                } else {//表示的是需要生产,消费者等待
                    try {
                        goods.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

class Productor implements Runnable {
    private Goods goods;

    public Productor(Goods goods) {
        this.goods = goods;
    }

    @Override
    public void run() {
        int count = 0;
        while (true) {
            synchronized (goods) {
                if (goods.isProductor()) {//true,表示需要生产
                    //若是奇数的话就生产幻影,若是偶数的话就生产 s9
                    if (count % 2 == 0) {//偶数
                        goods.setName("幻影");
                        goods.setPrice(9.9);
                    } else {
                        goods.setName("s9");
                        goods.setPrice(8.8);
                    }
                    count++;
                    //更改标记
                    goods.setProductor(false);
                    //唤醒消费者
                    goods.notify();
                } else {//表示不需要生产
                    try {
                        goods.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

public class Demo4 {
    public static void main(String[] args) {
        Goods goods = new Goods("五菱", 6.6, false);
        Customer customer = new Customer(goods);
        Productor productor = new Productor(goods);
        new Thread(customer).start();
        new Thread(productor).start();
    }
}

goods.notify();
} else {//表示不需要生产
try {
goods.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}

public class Demo4 {
public static void main(String[] args) {
Goods goods = new Goods(“五菱”, 6.6, false);
Customer customer = new Customer(goods);
Productor productor = new Productor(goods);
new Thread(customer).start();
new Thread(productor).start();
}
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值